简体   繁体   English

重写Paint方法时,不显示JTextField

[英]JTextField doesn't show when the Paint method is overridden

I'm writing a simple color chooser in java and I added a few JTextFields to get user input. 我正在用Java语言编写一个简单的颜色选择器,并添加了一些JTextFields以获取用户输入。 I added the text fields to a JPanel , but for some reason, they don't appear when I override the paint method. 我将文本字段添加到JPanel ,但是由于某些原因,当我覆盖paint方法时,它们不会出现。 When I run the program without overriding the paint method, though, the text fields show up. 但是,当我在不覆盖paint方法的情况下运行该程序时,将显示文本字段。 I know that they exist though, since the cursor changes when I hover over them, and if I add tool tip text, it shows up too. 我知道它们的存在,因为当我将鼠标悬停在它们上方时,光标会发生变化,并且如果添加工具提示文本,它也会显示出来。 How do I get the text fields to show up? 如何显示文本字段? Here is the code: 这是代码:

public class ColorSlider extends JPanel {
private ColorChooser parent;
private int sliderX = 0;
private JTextField textField = new JTextField();


    public ColorSlider(ColorChooser parent, int x, int y, String toolTip) {
            this.parent = parent;
            parent.add(this);
            setBounds(x, y, 96, 16);
            setVisible(true);
            setOpaque(false);
            setFocusable(true);
            addMouseListener(this);
            addMouseMotionListener(this);
            setToolTipText(toolTip);
            setLayout(null);
            textField.setBounds(80, 0, 16, 16); // Yes, I know this is way too small
            textField.setText("Text");
            add(textField);
    }

    @Override
    public void paint(Graphics g) {
            g.setColor(new Color(0xDDDDE1));
            g.fillRect(0, 4, 80, 8);
            g.setColor(new Color(0x444448));
            g.fillRect(sliderX, 0, 8, 16);
    }

Start by taking a look at Performing Custom Painting and Painting in AWT and Swing 首先看一下在AWT和Swing中 执行自定义绘画绘画

Essentially what you've done is broken the paint chain. 从本质上讲,您所做的就是打破油漆链。 Painting is made up of a series of chained method calls, each method adding something to the process, background, border, children...etc. 绘画是由一系列链接的方法调用组成的,每种方法都会在过程,背景,边框,子项等中添加一些内容。

By overriding paint and failing to call super.paint , you've prevented the panel from painting it's children. 通过重写paint并无法调用super.paint ,可以防止面板为子级绘画。

Now, you could override paintComponent instead (ensuring that you call super.paintComponent ), you could still end up with issues, as the painting is done behind the child components. 现在,您可以改写paintComponent (确保您调用super.paintComponent ),仍然会super.paintComponent问题,因为绘制是在子组件后面完成的。

A better (and simpler) solution would be to create two JPanel s and use there background color properties to simply change the color as you need. 更好(更简单)的解决方案是创建两个JPanel并在那里使用background颜色属性以根据需要简单地更改颜色。

Don't use null layouts, pixel perfect layouts are an illusion in modern GUI design, you don't control how the rendering works on different platforms, in particular how fonts are rendered. 不要使用null布局,像素完美布局是现代GUI设计中的一种错觉,您无法控制渲染在不同平台上的工作方式,尤其是字体的渲染方式。

Make use of appropriate layout managers 利用适当的布局管理器

Additional... 额外...

Separate the areas of responsibility. 分开负责的领域。 The "slider" is responsible for ... sliding. “滑块”负责...的滑动。 Create a component which does nothing but provides that functionality. 创建一个仅提供该功能的组件。 Then create another component which uses this slider and a JTextField to introduce extended functionality... 然后创建另一个组件,该组件使用此滑块和JTextField引入扩展功能...

在此处输入图片说明

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

public class ColorSliderTest {

    public static void main(String[] args) {
        new ColorSliderTest();
    }

    public ColorSliderTest() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new ColorSliderPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class ColorSliderPane extends JPanel {

        private final ColorSliderControl colorSliderControl;
        private final JTextField field;

        public ColorSliderPane() {
            field = new JTextField(5);
            colorSliderControl = new ColorSliderControl();
            setLayout(new BorderLayout());
            add(colorSliderControl);
            JPanel filler = new JPanel();
            filler.add(field);
            add(filler, BorderLayout.SOUTH);
        }

    }

    public class ColorSliderControl extends JPanel {

        private int sliderX;

        public ColorSliderControl() {
            setOpaque(false);
            setBorder(new EmptyBorder(4, 4, 4, 4));
        }

        @Override
        public Dimension getPreferredSize() {
            Insets insets = getInsets();
            int width = 80 + (insets.left + insets.right);
            int height = 16 + (insets.top + insets.bottom);
            return new Dimension(width, height);
        }

        @Override
        public void paint(Graphics g) {

            Insets insets = getInsets();

            int y = getHeight() / 2;
            int x = insets.left;
            int width = getWidth() - (insets.left + insets.right);

            g.setColor(new Color(0xDDDDE1));
            g.fillRect(x, y - 4, width, 8);

            g.setColor(new Color(0x444448));
            g.fillRect(sliderX + x, y - 8, 8, 16);

        }
    }

}

Before you say "but I want the field to the right", change 在您说“但我希望字段在右边”之前,请先更改

add(filler, BorderLayout.SOUTH);

to

add(filler, BorderLayout.EAST);

I might also mention JSlider 我可能还会提到JSlider

I think you've painted over them. 我想你已经画了他们。

This is a singularly awful way to treat your UI code; 这是一种处理UI代码的绝妙方法。 just what is it you are trying to accomplish by having two rectangles with hard-coded colors at hard-coded positions in your panel? 您要通过在面板的硬编码位置上放置两个具有硬编码颜色的矩形来实现什么目的?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM