Качайте «артефакты» в Linux для очень простой программы с графическим интерфейсом - PullRequest
0 голосов
/ 07 сентября 2018

Я изучаю Java и Swing через книгу (Filthy Rich Clients, не процитировать ее), и я попробовал следующий короткий пример кода для 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 я не обнаружил артефактов) и что нужно / можно сделать, чтобы исправить эту «ошибку»?

Я также заметил, что простой вызов super.paintComponent(Graphics g); только в начале paintComponent метода решает проблему. Но, что очень любопытно, авторы книги утверждают, что в данном конкретном случае звонок на super.paintComponent() не нужен.

Мой главный вопрос: почему я наблюдаю этот черный артефакт в моем окне Java?

1 Ответ

0 голосов
/ 08 сентября 2018

Так же, как и Пол, я не заметил артефакт внизу с правой стороны, как видно на скриншоте выше. Сказав это, это, вероятно, вызвано невозможностью вызова супер-метода. При его вызове фон компонента будет окрашен.

Вот еще один совет, который я бы порекомендовал реализовать в коде, с комментариями кода перед каждым, чтобы обсудить почему.

// 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);
    }
}
...