绘制使用自己的 Painter 创建的 JPanel

Posted

技术标签:

【中文标题】绘制使用自己的 Painter 创建的 JPanel【英文标题】:Painting the JPanel which created with own Painter 【发布时间】:2016-05-10 04:21:16 【问题描述】:

我需要学习如何更改创建自己的 Painter 方法的JPanel 颜色的逻辑。我创建了一个示例项目用于说明;

问题:按钮操作中的直接颜色更改代码不会改变任何内容。

问题 1) 覆盖 paintComponent 方法是否适合在创建面板时使用 JPanel 绘制 Gradient 颜色?

问题 2) 如何将 JPanel 的背景颜色更改为其他 Gradient 颜色或 Direct 颜色?

--代码--

package tryingproject2;

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class TryingProject2 

    public static void main(String[] args) 

        class ImagePanel extends JPanel

            public void paintComponent( Graphics g ) 
                Graphics2D g2d = (Graphics2D) g;
                int w = getWidth();
                int h = getHeight();
                Color color1;
                Color color2;
                color1 = new Color(223,130,24,255);
                color2 = new Color(255,255,255,255);

                GradientPaint gp = new GradientPaint(0, 0, color1, w, 0, color2);
                g2d.setPaint(gp);
                g2d.fillRect(0, 0, w, h);
            

        

        JFrame frame = new JFrame();
        frame.setLayout(null);
        frame.setSize(400,400);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel userPanel = new ImagePanel();
        userPanel.setBounds(100, 40, 200, 200);
        userPanel.setLayout(null);

        JLabel newLabel = new JLabel("Sample Label");
        newLabel.setBounds(50, 10, 100, 100);
        userPanel.add(newLabel);


        JButton button = new JButton("Change Color To Red");
        button.setBounds(100, 300, 200, 40);
        button.addActionListener(new ActionListener()  
            public void actionPerformed(ActionEvent e)  
              userPanel.setBackground(Color.red);
              userPanel.repaint();
              System.out.println("Button Pressed.");
             
        );

        frame.add(userPanel);
        frame.add(button);
        frame.setVisible(true);

    


【问题讨论】:

当你重写paintComponent时,你的方法必须做的第一件事就是调用super.paintComponent(g); "问题 1) 是否覆盖paintComponent 方法是在面板创建时使用渐变颜色绘制JPanel 的正确方法? - 是的;但见 VGR 评论; *"问题 2) 如何用其他渐变颜色或直接颜色更改此 JPanel 的背景颜色? - 使用实例字段存储当前值,使用 setter 更改它们并使用 getter 检索它们,调用repaint 在组件上安排重绘。 避免使用null 布局,像素完美的布局是现代用户界面设计中的一种错觉。影响组件单个尺寸的因素太多,您无法控制。 Swing 旨在与核心布局管理器一起工作,丢弃这些将导致无穷无尽的问题和问题,您将花费越来越多的时间来尝试纠正 【参考方案1】:

我重新排列了您的一些代码以解决其他问题。

这是我创建的 GUI。

这是我左键单击按钮后的 GUI。

我对您的代码进行了以下更改。

    我将所有 JFrame 代码移到一个 run 方法中,这样我就可以尽快摆脱静态方法并进入面向对象的类和方法中。

    我添加了对 SwingUtilitiles 的 invokeLater 方法的调用,以确保在 Event Dispatch thread 上创建和修改 Swing 组件。

    我创建了一个 createMainPanel 方法来创建主面板。我没有使用带有像素精度设置的丑陋空布局,而是使用了Swing layout(BorderLayout)来定位组件。这允许用户扩展 GUI 以填充屏幕,以及适合具有不同屏幕尺寸的不同计算机的 GUI。

    ImagePanel 类是一个完整的一流 Java 类。这意味着您可以拥有类字段和类构造函数。我提供了一种从课外设置颜色的方法。如果您不想要渐变,请将两种颜色设置为相同的颜色。

    ImagePanel 类的paintComponent 方法应以超级调用开始,以维护Swing Paint 链。 paintComponent 方法除了绘画什么都不做。时期。句号。没有其他的。与绘画无关的代码我删除了。

    查看 createMainPanel 方法中的 actionPerformed 方法,您会看到我如何更改其中一种渐变颜色并执行重绘。动作侦听器是您的 GUI 的控制器。只有控制器代码应该更改模型(ImagePanel 中的颜色)或视图(ImagePanel 和 JFrame)。在创建 Swing GUI 时始终查找 model / view / controller pattern。

这是修改后的代码。

package com.ggl.testing;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TryingProject2 implements Runnable 

    public static void main(String[] args) 
        SwingUtilities.invokeLater(new TryingProject2());
    

    @Override
    public void run() 
        JFrame frame = new JFrame("Color Gradient Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createMainPanel());
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    

    private JPanel createMainPanel() 
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());

        JPanel imageLabelPanel = new JPanel();
        imageLabelPanel.setLayout(new BorderLayout());

        final ImagePanel imagePanel = new ImagePanel(new Color(223, 130, 24,
                255), new Color(255, 255, 255, 255));
        imageLabelPanel.add(imagePanel, BorderLayout.CENTER);

        JLabel newLabel = new JLabel("Sample Label");
        newLabel.setHorizontalAlignment(JLabel.CENTER);
        imageLabelPanel.add(newLabel, BorderLayout.SOUTH);

        panel.add(imageLabelPanel, BorderLayout.CENTER);

        JButton button = new JButton("Change Color To Red");
        button.addActionListener(new ActionListener() 
            public void actionPerformed(ActionEvent e) 
                imagePanel.setColor1(Color.RED);
                imagePanel.repaint();
                System.out.println("Button Pressed.");
            
        );
        panel.add(button, BorderLayout.SOUTH);

        return panel;
    

    public class ImagePanel extends JPanel 

        private static final long serialVersionUID = 6970287820048941335L;

        private Color color1;
        private Color color2;

        public ImagePanel(Color color1, Color color2) 
            this.color1 = color1;
            this.color2 = color2;
            this.setPreferredSize(new Dimension(200, 200));
        

        public void setColor1(Color color1) 
            this.color1 = color1;
        

        public void setColor2(Color color2) 
            this.color2 = color2;
        

        public void paintComponent(Graphics g) 
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g;
            int w = getWidth();
            int h = getHeight();

            GradientPaint gp = new GradientPaint(0, 0, color1, w, 0, color2);
            g2d.setPaint(gp);
            g2d.fillRect(0, 0, w, h);
        

    


【讨论】:

首先感谢吉尔伯特的努力。这个真的很有借鉴意义。我从你的代码中学到了一些机制。但是我使用 NetBeans GUI Builder 来创建 GUI,并且我有很多 JPanel 用于更改颜色取决于一些 if else 语句。我如何将您的解决方案实施到我还不知道的整个真实项目中。但请仔细阅读您的示例,谢谢。 我以非常不同的方式解决了我的问题。很难解释,但这个解决方案足以说明这个问题。我会接受答案。再次感谢您。

以上是关于绘制使用自己的 Painter 创建的 JPanel的主要内容,如果未能解决你的问题,请参考以下文章

HT for Web 中Painter的介绍及用法

HT for Web 中Painter的介绍及用法

QT中painter event的使用问题

绘制文本QPainterQPainterPathQBrush

使用 QPainter 绘制带有渐变边缘的直线和曲线

little tips of painter.drawRect in Qt