简体   繁体   中英

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. I added the text fields to a JPanel , but for some reason, they don't appear when I override the paint method. When I run the program without overriding the paint method, though, the text fields show up. 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

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.

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.

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.

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.

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...

在此处输入图片说明

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

I think you've painted over them.

This is a singularly awful way to treat your UI code; just what is it you are trying to accomplish by having two rectangles with hard-coded colors at hard-coded positions in your panel?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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