【问题标题】:Repaint() between different classes does not update不同类之间的 Repaint() 不会更新
【发布时间】:2013-04-06 16:17:36
【问题描述】:

我正在尝试制作一个简单的文字处理器,其中 JFrame 顶部有一个 ControlPanel,中间有一个带有 JTextArea 组件的 TextPanel。我的程序的基本概述是有一个名为 MyPanel 的 JPanel,它占据了整个 JFrame 并保存了其余的面板。 MyPanel 内部是 ControlPanel 和 TextPanel(未嵌套)。 ControlPanel 包含用于字体样式的各种 JButton 和 JComboBoxes,而 TextPanel 仅具有 JTextArea。

我想要的是,当我按下 ControlPanel 类中的 JButton(例如 BOLD)时,它将转到 actionPerformed() 并执行“text.repaint”。但我发现 text.repaint 甚至没有进入 TextPanel 并且从未进入 paintComponent 方法。我尝试将 ControlPanel 嵌套在 TextPanel 中并给它一个 BorderLayout.NORTH,效果很好,但是看起来纸张连接到了控制面板,这是我不喜欢的。

谁能给我一个替代方案或解释为什么 text.repaint() 不起作用?

这是我的代码的重要部分供参考:(重要部分用//标记)

注意:类 ControlPanel 和类 TextPanel 没有对齐,因为我懒得在一个平庸的文本编辑器上修复对齐。相信我,它们没有嵌套,并且都在 MyPanel 类中

        class ControlPanel extends JPanel implements ActionListener
        {
            JButton bold, italics;
            JComboBox font;
            JComboBox size;
            String [] fontsizes = {"8", "10", "12", "16", "20", "24", "36", "48", "56", "72"};
            String [] fonttypes = {"Arial", "Serif", "Sans Serif", "Gothic", "Helvetica", "Times New Roman", "Comic Sans"};

            public ControlPanel() // class ControlPanel control
            {
                setBackground(Color.gray);
                this.setLayout(new FlowLayout());

                Font boldfont = new Font("Serif", Font.BOLD, 16);
                bold = new JButton("B");
                bold.setFont(boldfont);
                //bold.getModel().setPressed(true);
                bold.addActionListener(this);
                this.add(bold);

                Font italicsfont = new Font("Serif", Font.ITALIC, 16);
                italics = new JButton("I");
                italics.setFont(italicsfont);
                //italics.getModel().setPressed(true);
                italics.addActionListener(this);
                this.add(italics);

                font = new JComboBox(fonttypes);
                font.setSelectedIndex(0);
                font.addActionListener(this);
                this.add(font);

                size = new JComboBox(fontsizes);
                size.setSelectedIndex(2);
                size.addActionListener(this);
                size.setEditable(true);
                this.add(size);

            }

            public void actionPerformed(ActionEvent e)
            {
                String command = e.getActionCommand();
                if (command.equals("B"))
                {
                    if (boldfont)
                        boldfont = false;
                    else
                        boldfont = true;
                }
                if (command.equals("I"))
                {
                    if (italicsfont)
                        italicsfont = false;
                    else 
                        italicsfont = true;
                }
                fontselection = (String)font.getSelectedItem();
                sizeselection = Integer.parseInt((String)(size.getSelectedItem()));
                text.repaint(); // repaints TextPanel text class
            }
        }

    class TextPanel extends JPanel // class TextPanel text
    {
        JTextArea type;

        public TextPanel()
        {
            this.setLayout(new BorderLayout());
            type = new JTextArea();
            type.setEditable(true);
            type.setLineWrap(true);
            type.setWrapStyleWord(true);
            type.setTabSize(4);
            type.setMargin(new Insets(80, 100, 80, 100));
            this.add(type, BorderLayout.CENTER);
        }


        public void paintComponent(Graphics g) // paintComponent() method for TextPanel
        {
            System.out.println("paintComponent of text"); // does not print out in terminal
            super.paintComponent(g);
            Font regfont;
            int fontstyle = 0;
            regfont = new Font("Arial", Font.PLAIN, 12);
            if (boldfont)
            {
                fontstyle = 1;
            }
            else if (!boldfont)
            {
                fontstyle = 0;
            }
            if (italicsfont)
            {
                if (boldfont)
                    fontstyle = 3;
                else
                    fontstyle = 2;
            }
            else if (!italicsfont)
            {
                if (boldfont)
                    fontstyle = 1;
                else
                    fontstyle = 0;
            }
            regfont = new Font(fontselection, fontstyle, sizeselection);
            type.setFont(regfont);
        }
    }

【问题讨论】:

    标签: java swing actionlistener repaint paintcomponent


    【解决方案1】:

    您的paint 方法不会向整个应用程序添加任何功能。实际上,您最好允许控制窗格将状态请求传递给TextPane,然后直接影响文本区域。

    基本上,您在 paintComponent 方法中所做的事情对于您正在尝试的事情是错误的,并且实际上可能会产生可能消耗您的 CPU 的循环重绘调用场景

    更新示例

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.EventQueue;
    import java.awt.FlowLayout;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.Insets;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JComboBox;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextArea;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class TestTextPane01 {
    
        public static void main(String[] args) {
            new TestTextPane01();
        }
    
        public TestTextPane01() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    TextPanel textPanel = new TextPanel();
                    ControlPanel controlPanel = new ControlPanel(textPanel);
    
                    JFrame frame = new JFrame("Test");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(controlPanel, BorderLayout.NORTH);
                    frame.add(textPanel);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
    
            });
        }
    
    
    
        class ControlPanel extends JPanel implements ActionListener {
    
            JButton bold, italics;
            JComboBox font;
            JComboBox size;
            String[] fontsizes = {"8", "10", "12", "16", "20", "24", "36", "48", "56", "72"};
            String[] fonttypes = {"Arial", "Serif", "Sans Serif", "Gothic", "Helvetica", "Times New Roman", "Comic Sans"};
            private boolean boldfont;
            private boolean italicsfont;
            private String fontselection;
            private int sizeselection;
            private TextPanel textPane;
    
            public ControlPanel(TextPanel txtPanel) // class ControlPanel control
            {
                textPane = txtPanel;
                setBackground(Color.gray);
                this.setLayout(new FlowLayout());
    
                Font boldfont = new Font("Serif", Font.BOLD, 16);
                bold = new JButton("B");
                bold.setFont(boldfont);
                //bold.getModel().setPressed(true);
                bold.addActionListener(this);
                this.add(bold);
    
                Font italicsfont = new Font("Serif", Font.ITALIC, 16);
                italics = new JButton("I");
                italics.setFont(italicsfont);
                //italics.getModel().setPressed(true);
                italics.addActionListener(this);
                this.add(italics);
    
                font = new JComboBox(fonttypes);
                font.setSelectedIndex(0);
                font.addActionListener(this);
                this.add(font);
    
                size = new JComboBox(fontsizes);
                size.setSelectedIndex(2);
                size.addActionListener(this);
                size.setEditable(true);
                this.add(size);
    
            }
    
            public void actionPerformed(ActionEvent e) {
                String command = e.getActionCommand();
                if (command.equals("B")) {
                    boldfont = !boldfont;
                } else if (command.equals("I")) {
                    italicsfont = !italicsfont;
                }
                fontselection = (String) font.getSelectedItem();
                sizeselection = Integer.parseInt((String) (size.getSelectedItem()));
    //            text.repaint(); // repaints TextPanel text class
                textPane.setFont(boldfont, italicsfont);
            }
    
        }
    
        class TextPanel extends JPanel // class TextPanel text
        {
    
            JTextArea type;
    
            public TextPanel() {
                this.setLayout(new BorderLayout());
                type = new JTextArea();
                type.setEditable(true);
                type.setLineWrap(true);
                type.setWrapStyleWord(true);
                type.setTabSize(4);
                type.setMargin(new Insets(80, 100, 80, 100));
                this.add(type, BorderLayout.CENTER);
            }
    
            public void setFont(boolean boldFont, boolean italicsFont) {
                Font font = type.getFont();
                int style = Font.PLAIN;
                if (boldFont && italicsFont) {
                    style = Font.BOLD | Font.ITALIC;
                } else if (boldFont) {
                    style = Font.BOLD;
                } else if (italicsFont) {
                    style = Font.ITALIC;
                }
                font = font.deriveFont(style);
                System.out.println("Font");
                type.setFont(font);
            }
    
        }
    
    }
    

    我还建议您阅读 How to Use Scroll PanesPerforming Custom PaintingPainting in AWT and Swing

    【讨论】:

    • 非常感谢!它工作得很好,我想我明白了一切。我只有几个一般性的问题:你认为什么时候可以使用绘画方法?当布尔字体和斜体字体已经是可访问的变量时,为什么还要将它们传递给 setFont() 呢?这只是你个人的喜好还是只是一个好习惯?再次感谢!
    • 我可能选择覆盖 paint 的唯一可能原因是如果我想在组件及其所有子组件的顶部进行绘制,但这很容易被他们可能选择的重绘管理器覆盖不要重绘容器(因为孩子们在它上面)。我将boolean 标志传递给TextPane 的原因是因为管理这些标志是TextPanes 的责任,没有其他人。这也意味着我隔离了可能发生更新的位置。所以唯一的改变方法是通过setFont方法
    • 我应该补充一点,如果打算覆盖 paint,我可能会考虑使用 JXLayer 或 GlassPane 之类的东西
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 2019-11-01
    • 1970-01-01
    • 2012-11-07
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    相关资源
    最近更新 更多