8

I am currently developing a kiosk style Java program to display weather, time, forecast etc. Here is a shot of what the program should look like (screenshot taken before the time updated)

Image showing required output before the graphical error

The various sections are created as JPanels with the paintComponent() method overridden. They draw in a gradient header and a semitransparent background. However, when I change the content of one of these panels, the previous content is left behind, rather than being removed. An example is shown below:

As you can see, when the time changed from 11:51 to 11:52, the numbers overlapped, and the background became lighter (because the semitransparent background was redrawn over it)

The Graphical Error

Image showing the graphical error

What should I do to prevent this overlap? Ultimately, I would prefer to not have to redraw the entire screen when an individual panel updates it's contents. I would prefer to only redraw that particular section. It would be easy to repaint the background, and then all the components within.

Update

Several answers involve clearing the area to be drawn. Whether I use g.clear() or AlphaComposite.CLEAR it erases the background image. this can be seen in the following image. Perhaps if I could copy the background before I clear the area, I could repaint that section of the background, then layer the other images appropriately. Thoughts?

enter image description here

Update 2

An answer was submitted which shows a complete working example of a timer laid over a transparent panel and a background. This is very useful, however, I am not painting my sub-componenets manually. The time, weather icons and temperatures are all JLabels laid out over the semi-transparent panel. I would prefer to not have to paint the individual components manually.

4

3 回答 3

4

类似的问题

之前的图像

在这里解决

之后的图像

还要注意,“Swing 程序应该覆盖paintComponent()而不是覆盖paint()。”—<a href="https://www.oracle.com/technetwork/java/index.html#callbacks" rel="nofollow noreferrer">在 AWT 中绘画和Swing:绘制方法

于 2012-07-27T17:27:55.550 回答
3

在进行绘画之前,请先调用 g.clearRect(0,0,w,h)。这将删除指定区域中的所有内容,并且您不会在前一帧的顶部进行绘制。

您可能需要应用一些双缓冲技术,因为您的屏幕会因为清晰而轻微闪烁。

于 2012-07-27T16:03:49.210 回答
3

我很快就把它放在一起了,没什么特别的......

在此处输入图像描述

整个项目由一个 JFrame、一个 BackgroundImagePane 和 ClockPane 组成

ClockPane 看起来像这样(因为您可以重新创建其余部分;))

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.Timer;

public class ClockPane extends javax.swing.JPanel {

    private Timer tick;

    protected static final SimpleDateFormat SDF = new SimpleDateFormat("HH:mm.ss");

    public ClockPane() {

        setOpaque(false);

        tick = new Timer(500, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {

                repaint();

            }

        });

        tick.setCoalesce(true);
        tick.setRepeats(true);

        setPreferredSize(new Dimension(100, 100));
        setMinimumSize(new Dimension(100, 100));

    }

    @Override
    public void addNotify() {

        super.addNotify();

        tick.start();

    }

    @Override
    public void removeNotify() {

        tick.stop();

        super.removeNotify();

    }

    @Override
    protected void paintComponent(Graphics grphcs) {

        super.paintComponent(grphcs);

        Graphics2D g2d = (Graphics2D) grphcs;

        int width = getWidth() - 1;
        int height = getHeight() - 1;

        Color background = new Color(192, 192, 192, 128);
        Color border = new Color(128, 128, 128);
        RoundRectangle2D backing = new RoundRectangle2D.Float(0, 0, width, height, 20, 20);

        g2d.setPaint(background);
        g2d.fill(backing);
        g2d.setPaint(border);
        g2d.draw(backing);

        String text = SDF.format(new Date());
        FontMetrics fm = g2d.getFontMetrics();
        g2d.setPaint(Color.BLACK);

        int x = (width - fm.stringWidth(text)) / 2;
        int y = ((height - fm.getHeight()) / 2) + fm.getAscent();

        g2d.drawString(text, x, y);

    }

}

有了这个,时钟每半秒左右更新一次,我对重绘没有任何问题

我能想到的唯一有意义的是setOpaque(false);

更新

这个例子完全是用标签和面板完成的(背景窗格是一个自定义的绘画工作,日期标签也有它的背景,但除此之外)

正常组件

现在,我把我的一起黑了,所以它不如你的好,但话又说回来,我没有得到报酬;)

import core.ui.UIUtilities;
import core.ui.WindowUtilities;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.Timer;
import javax.swing.UIManager;

public class MainFrame extends javax.swing.JFrame {

    /**
     * Creates new form MainFrame
     */
    public MainFrame() {

        setUndecorated(true);
        WindowUtilities.setOpaque(this, false);

        initComponents();

        Timer timer = new Timer(500, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                lblTime.setText(new SimpleDateFormat("hh:MM:ss").format(new Date()));

            }
        });

        timer.setRepeats(true);
        timer.setCoalesce(true);
        timer.start();

        DateLabel label = new DateLabel();
        label.init();

        NewBackgroundPane backgroundPane = new NewBackgroundPane();
        backgroundPane.setLayout(new BorderLayout());
        backgroundPane.add(label, BorderLayout.NORTH);
        backgroundPane.add(pnlMain);

        add(backgroundPane, BorderLayout.CENTER);

        pack();

        setLocation(UIUtilities.centerOfDefaultScreen(this));

    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        pnlMain = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        lblTime = new javax.swing.JLabel();
        lblExtTime = new javax.swing.JLabel();
        jPanel3 = new javax.swing.JPanel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jPanel4 = new javax.swing.JPanel();
        jPanel5 = new javax.swing.JPanel();
        jLabel11 = new javax.swing.JLabel();
        jLabel12 = new javax.swing.JLabel();
        jLabel13 = new javax.swing.JLabel();
        jLabel14 = new javax.swing.JLabel();
        jPanel6 = new javax.swing.JPanel();
        jLabel15 = new javax.swing.JLabel();
        jLabel16 = new javax.swing.JLabel();
        jLabel17 = new javax.swing.JLabel();
        jLabel18 = new javax.swing.JLabel();
        jPanel7 = new javax.swing.JPanel();
        jLabel19 = new javax.swing.JLabel();
        jLabel20 = new javax.swing.JLabel();
        jLabel21 = new javax.swing.JLabel();
        jLabel22 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        pnlMain.setOpaque(false);
        pnlMain.setLayout(new java.awt.GridBagLayout());

        jPanel2.setOpaque(false);
        jPanel2.setLayout(new java.awt.GridBagLayout());

        lblTime.setFont(lblTime.getFont().deriveFont(lblTime.getFont().getStyle() | java.awt.Font.BOLD, lblTime.getFont().getSize()+18));
        lblTime.setForeground(new java.awt.Color(255, 255, 255));
        lblTime.setText("jLabel1");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        jPanel2.add(lblTime, gridBagConstraints);

        lblExtTime.setFont(lblExtTime.getFont().deriveFont(lblExtTime.getFont().getSize()+6f));
        lblExtTime.setForeground(new java.awt.Color(255, 255, 255));
        lblExtTime.setText("AM EDT");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_START;
        jPanel2.add(lblExtTime, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        pnlMain.add(jPanel2, gridBagConstraints);

        jPanel3.setOpaque(false);
        jPanel3.setLayout(new java.awt.GridBagLayout());

        jLabel3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/transparentUpdate/Overcast.png"))); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 2;
        jPanel3.add(jLabel3, gridBagConstraints);

        jLabel4.setFont(jLabel4.getFont().deriveFont(jLabel4.getFont().getSize()+6f));
        jLabel4.setForeground(new java.awt.Color(255, 255, 255));
        jLabel4.setText("<html>Currenctly<br>Overast</html>");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
        jPanel3.add(jLabel4, gridBagConstraints);

        jLabel5.setFont(jLabel5.getFont().deriveFont(jLabel5.getFont().getSize()+12f));
        jLabel5.setForeground(new java.awt.Color(255, 255, 255));
        jLabel5.setText("69");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LAST_LINE_START;
        jPanel3.add(jLabel5, gridBagConstraints);

        jLabel6.setForeground(new java.awt.Color(255, 255, 255));
        jLabel6.setText("/65");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LAST_LINE_START;
        jPanel3.add(jLabel6, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        pnlMain.add(jPanel3, gridBagConstraints);

        jPanel4.setOpaque(false);
        jPanel4.setLayout(new java.awt.GridBagLayout());

        jPanel5.setOpaque(false);
        jPanel5.setLayout(new java.awt.GridBagLayout());

        jLabel11.setFont(jLabel11.getFont().deriveFont(jLabel11.getFont().getSize()+4f));
        jLabel11.setForeground(new java.awt.Color(255, 255, 255));
        jLabel11.setText("Today");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 2;
        jPanel5.add(jLabel11, gridBagConstraints);

        jLabel12.setForeground(new java.awt.Color(255, 255, 255));
        jLabel12.setIcon(new javax.swing.ImageIcon(getClass().getResource("/transparentUpdate/SmallOvercast.png"))); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridheight = 2;
        jPanel5.add(jLabel12, gridBagConstraints);

        jLabel13.setFont(jLabel13.getFont().deriveFont(jLabel13.getFont().getSize()+4f));
        jLabel13.setForeground(new java.awt.Color(255, 255, 255));
        jLabel13.setText("83");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_START;
        jPanel5.add(jLabel13, gridBagConstraints);

        jLabel14.setForeground(new java.awt.Color(255, 255, 255));
        jLabel14.setText("65");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_START;
        jPanel5.add(jLabel14, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_START;
        gridBagConstraints.insets = new java.awt.Insets(2, 4, 2, 4);
        jPanel4.add(jPanel5, gridBagConstraints);

        jPanel6.setOpaque(false);
        jPanel6.setLayout(new java.awt.GridBagLayout());

        jLabel15.setFont(jLabel15.getFont().deriveFont(jLabel15.getFont().getSize()+4f));
        jLabel15.setForeground(new java.awt.Color(255, 255, 255));
        jLabel15.setText("Sunday");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 2;
        jPanel6.add(jLabel15, gridBagConstraints);

        jLabel16.setForeground(new java.awt.Color(255, 255, 255));
        jLabel16.setIcon(new javax.swing.ImageIcon(getClass().getResource("/transparentUpdate/Sunny.png"))); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridheight = 2;
        jPanel6.add(jLabel16, gridBagConstraints);

        jLabel17.setFont(jLabel17.getFont().deriveFont(jLabel17.getFont().getSize()+4f));
        jLabel17.setForeground(new java.awt.Color(255, 255, 255));
        jLabel17.setText("82");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_START;
        jPanel6.add(jLabel17, gridBagConstraints);

        jLabel18.setForeground(new java.awt.Color(255, 255, 255));
        jLabel18.setText("64");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_START;
        jPanel6.add(jLabel18, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_START;
        gridBagConstraints.insets = new java.awt.Insets(2, 4, 2, 4);
        jPanel4.add(jPanel6, gridBagConstraints);

        jPanel7.setOpaque(false);
        jPanel7.setLayout(new java.awt.GridBagLayout());

        jLabel19.setFont(jLabel19.getFont().deriveFont(jLabel19.getFont().getSize()+4f));
        jLabel19.setForeground(new java.awt.Color(255, 255, 255));
        jLabel19.setText("Monday");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 2;
        jPanel7.add(jLabel19, gridBagConstraints);

        jLabel20.setForeground(new java.awt.Color(255, 255, 255));
        jLabel20.setIcon(new javax.swing.ImageIcon(getClass().getResource("/transparentUpdate/Cloudy.png"))); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridheight = 2;
        jPanel7.add(jLabel20, gridBagConstraints);

        jLabel21.setFont(jLabel21.getFont().deriveFont(jLabel21.getFont().getSize()+4f));
        jLabel21.setForeground(new java.awt.Color(255, 255, 255));
        jLabel21.setText("83");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_START;
        jPanel7.add(jLabel21, gridBagConstraints);

        jLabel22.setForeground(new java.awt.Color(255, 255, 255));
        jLabel22.setText("84");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_START;
        jPanel7.add(jLabel22, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_START;
        gridBagConstraints.insets = new java.awt.Insets(2, 4, 2, 4);
        jPanel4.add(jPanel7, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        pnlMain.add(jPanel4, gridBagConstraints);

        getContentPane().add(pnlMain, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {

            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new MainFrame().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel13;
    private javax.swing.JLabel jLabel14;
    private javax.swing.JLabel jLabel15;
    private javax.swing.JLabel jLabel16;
    private javax.swing.JLabel jLabel17;
    private javax.swing.JLabel jLabel18;
    private javax.swing.JLabel jLabel19;
    private javax.swing.JLabel jLabel20;
    private javax.swing.JLabel jLabel21;
    private javax.swing.JLabel jLabel22;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JLabel lblExtTime;
    private javax.swing.JLabel lblTime;
    private javax.swing.JPanel pnlMain;
    // End of variables declaration
}

只是为了让生活更轻松,背景窗格

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;

public class NewBackgroundPane extends javax.swing.JPanel {

    /**
     * Creates new form NewBackgroundPane
     */
    public NewBackgroundPane() {
        initComponents();
    }

    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g.create();

        int width = getWidth() - 1;
        int height = getHeight() - 1;

        g2d.setColor(Color.LIGHT_GRAY);
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
        g2d.fillRoundRect(0, 0, width, height, 20, 20);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        setOpaque(false);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );
    }// </editor-fold>
    // Variables declaration - do not modify
    // End of variables declaration
}

如果你仍然无法让它工作,我能想到的唯一其他问题可能与全屏独占模式有关,我还没有测试过:P

于 2012-07-27T23:33:35.803 回答