java - 在 Linux 上使用 Swing «artifacts» 实现一个非常简单的 GUI 程序

标签 java swing jcomponent

我正在通过一本书(Filthy Rich Clients,不引用它)学习 Java 和 Swing,并且我在 Linux(Oracle JDK 8)上尝试了以下简短的示例代码:

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class OvalComponent extends JComponent {

    public void paintComponent(Graphics g) {
        g.setColor(getBackground());
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(Color.GRAY);
        g.fillOval(0, 0, getWidth(), getHeight());
    }

    private static void createAndShowGUI() {    
        JFrame f = new JFrame("Oval");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(200, 200);
        f.add(new OvalComponent());
        f.setVisible(true);
    }

    public static void main(String args[]) {
        Runnable doCreateAndShowGUI = new Runnable() {
            public void run() {
                createAndShowGUI();
            } 
        };
        SwingUtilities.invokeLater(doCreateAndShowGUI);
     }
}

当我运行此代码时,我奇怪地在 JFrame 边框上观察到以下“工件”:

artifact observed on JFrame

当拖动窗口时,这个“工件”仍然存在,但在调整大小时消失。我想了解为什么我在 Linux 上有这种奇怪的行为。这是 Linux 固有的吗(在 Windows 7 上我没有观察到任何工件),应该/可以做什么来修复这个“bug”?

我还观察到,只需在 paintComponent 方法的开头调用 super.paintComponent(Graphics g); 即可解决问题。但是,非常奇怪的是,书中的作者说,在这种特殊情况下,调用 super.paintComponent() 是不必要的。

我的主要问题是:为什么我会在 Java 窗口上观察到这个黑色伪像?

最佳答案

与 Paul 一样,我没有注意到右侧的伪影,如上面的屏幕截图所示。话虽如此,很有可能是没有调用super方法造成的。调用它将导致组件的背景被绘制。

以下是我建议在代码中实现的一些其他建议,并在每个建议之前添加代码注释来讨论原因。

// A JPanel does some things automatically, so I prefer to use one
//public class OvalComponent extends JComponent {
public class OvalComponent extends JPanel {

    // Use @Override notation! 
    @Override
    public void paintComponent(Graphics g) {
        // call the super method first..
        super.paintComponent(g);
        // this is better achieved with the call to super
        //g.setColor(getBackground());
        //g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(Color.GRAY);
        g.fillOval(0, 0, getWidth(), getHeight());
    }

    // suggest a size for the layout manager(s) to use..
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(300, 300);
    }

    private static void createAndShowGUI() {
        JFrame f = new JFrame("Oval");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // DON'T TRY TO GUESS WHAT SIZE THE FRAME SHOULD BE!
        // f.setSize(200, 200);
        f.add(new OvalComponent());
        // Instead pack the top level container after components added
        f.pack();
        f.setVisible(true);
    }

    public static void main(String args[]) {
        Runnable doCreateAndShowGUI = () -> {
            createAndShowGUI();
        };
        SwingUtilities.invokeLater(doCreateAndShowGUI);
    }
}

关于java - 在 Linux 上使用 Swing «artifacts» 实现一个非常简单的 GUI 程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52229262/

相关文章:

java - 限制 PLAIN_MESSAGE JOptionPane 中输入文本的大小

java - JFileChooser 和复制文件

java - 从 JList 中删除项目

java - 检测 JLabel(或类似的)何时被拖离组件

java - Gradle 同步失败 : Plugin with id 'com.google.android.gms:play-services' not found

java - 类似于 GenericDialog/ADM 的东西

Java Swing - 从鼠标监听器更改 JComponent 不透明度

java - 在 JTable 中显示组件的最佳方式?

java - Spring MVC安全: Error creating bean with name 'springSecurityFilterChain'

Java位图合成如何