Swing 组件在彼此内部绘制 [英] Swing components drawing inside each other

查看:24
本文介绍了Swing 组件在彼此内部绘制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我在大约两周内的第四个问题......我想我有很多东西要学.

This is my fourth question here in about two weeks... I think I have a lot to learn.

无论如何,我希望我在下面准备的示例能够比我能更好地解释问题,但是由于我将所有组件都更改为 Swing 而不是 AWT,因此它们一直在绘制面板中的每个组件每当我调用 repaint() 时,它们就在自己内部.

Anyway, I'm hoping the sample I've prepared below will explain the problem better than I can, but since I changed all of my components to Swing rather than AWT, they've all been drawing every component in the panel inside themselves whenever I call repaint().

这段代码本质上是我的程序在不完全破坏问题的情况下尽可能多地精简.我在那里贴了几个我的自定义列表框组件来演示这个问题,并将边框设为红色,以便更容易地查看绘制的内容.

This code is essentially my program stripped down as much as I can without destroying the problem completely. I've stuck a couple of my custom listbox components in there to demonstrate the issue, and made the border red to make it slightly easier to see what's drawing where.

Test.java:

package test;

import java.awt.image.*;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import javax.imageio.*;
import java.util.*;

public class Test extends JFrame
{
    public static void main(String[] args)
    {           
        Test test1 = new Test();
    }

    public Test()
    {
        super("Test Frame");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);                     
        setVisible(true);
        setSize(800, 480);
        setLocationRelativeTo(null);

        loadTestScreen();
    }   

    public void loadTestScreen()
    {
        TestScreen newTestScreen = new TestScreen();
        newTestScreen.setSize(new Dimension(getWidth() - getInsets().left - getInsets().right, getHeight() - getInsets().top - getInsets().bottom));
        setContentPane(newTestScreen);
    }

}

TestScreen.java:

package test;

import java.awt.image.*;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import javax.imageio.*;
import java.awt.event.ComponentListener;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.util.*;
import java.net.URI;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

public class TestScreen extends JPanel implements ComponentListener, MouseListener
{
    int border, LT;

    public TestScreen()
    {
        setLayout(null);
        setOpaque(true);
        setBackground(Color.WHITE);
        addComponentListener(this);

        border = 8;
        LT = 4;

        ///////////////////////////////////////////////////////////

        ArrayList<String> testList = new ArrayList<String>();
        testList.add("1");
        testList.add("2");
        testList.add("3");
        testList.add("4");
        testList.add("5");
        testList.add("6");

        add(new ListBox(testList), 0);
        add(new ListBox(testList), 1);
    }

    public void paintComponent(Graphics g)
    {
        Graphics2D g2d = (Graphics2D)g;
        g2d.setStroke(new BasicStroke((float)(LT)));

        g2d.setColor(new Color(255, 0, 0));
        g2d.drawRoundRect(border, border, getWidth() - border - border, getHeight() - border - border, border + border, border + border);
    }


    public void componentHidden(ComponentEvent e){}
    public void componentShown(ComponentEvent e){}
    public void componentMoved(ComponentEvent e)
    {
        componentResized(e);
    }
    public void componentResized(ComponentEvent e)
    {       
        getComponent(0).setLocation(20, 20);
        getComponent(0).setSize(100, 100);

        getComponent(1).setLocation(200, 200);
        getComponent(1).setSize(150, 150);

        repaint();
    }

    public void mouseEntered(MouseEvent e)
    {
            repaint();
    }
    public void mouseExited(MouseEvent e)
    {
            repaint();  
    }

    public void mouseReleased(MouseEvent e){}  public void mouseDragged(MouseEvent e){} public void mouseClicked(MouseEvent e){}

    public void mousePressed(MouseEvent e)
    {
        repaint();
    }
}

ListBox.java:

package test;

import java.beans.*;
import java.util.*;
import java.awt.*;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseMotionListener;
import java.awt.event.ComponentListener;
import java.awt.event.ComponentEvent;
import java.beans.PropertyChangeSupport;
import javax.swing.*;

public class ListBox extends JComponent implements MouseListener, MouseMotionListener, MouseWheelListener, ComponentListener
{
    public ArrayList<String> data;
    int border, LT;
    int selectedIndex = 0;
    int mousedIndex = -1;
    public int viewedHeight = 0;
    int itemHeight;
    int numberOfDisplayedItems;
    Font miniFont;
    FontMetrics miniMetrics;
    private final PropertyChangeSupport pcs = new PropertyChangeSupport( this );

    public ListBox(ArrayList<String> list)
    {
        setVisible(true);
        setOpaque(true);

        border = 8;
        LT = 4;

        addMouseListener(this);
        addMouseMotionListener(this);
        addComponentListener(this);
        addMouseWheelListener(this);

        data = list;
        miniFont = new Font("Calibri", Font.PLAIN, 15);
        miniMetrics = getFontMetrics(miniFont);

        itemHeight = miniMetrics.getAscent() + miniMetrics.getDescent() + border + border;
    }

    public void paintComponent(Graphics g)
    {   
        Graphics2D g2d = (Graphics2D)g;
        g2d.setColor(new Color(93, 138, 168));
        g2d.setStroke(new BasicStroke((float)LT / 2));
        g2d.setClip(-(LT / 2), -(LT / 2), getWidth() + LT, getHeight() + LT);

        int cumulativeDist = -viewedHeight;

        for (int i = 0; i < data.size(); i++)
        {
            if (selectedIndex == i)
                g2d.fillRect(0, cumulativeDist, getWidth(), itemHeight);

            cumulativeDist += itemHeight;
            g2d.drawLine(0, cumulativeDist, getWidth(), cumulativeDist);
        }
        g2d.drawRect(0, 0, getWidth(), getHeight());

        g2d.setFont(miniFont);
        g2d.setColor(new Color(42, 60, 76));

        cumulativeDist = -viewedHeight + border + miniMetrics.getAscent();

        for (int i = 0; i < data.size(); i++)
        {
            if (mousedIndex == i){
            g2d.drawString(data.get(i), border + border / 2, cumulativeDist);
            } else {
            g2d.drawString(data.get(i), border, cumulativeDist);
            }

            cumulativeDist += itemHeight;
        }

    }

    public String getSelectedItem()
    {
        return data.get(selectedIndex);
    }   
    public void mouseReleased(MouseEvent e){}  public void mouseEntered(MouseEvent e){}  public void mouseDragged(MouseEvent e){}public void mouseClicked(MouseEvent e){}

    public void mousePressed(MouseEvent e)
    {
        int old = selectedIndex;
        int mouseHeight = viewedHeight + e.getY();
        int ID = mouseHeight / itemHeight;
        System.out.println(mouseHeight / itemHeight);
        selectedIndex = ID;
        pcs.firePropertyChange("selectedIndex", old, selectedIndex);
    }

    public void componentHidden(ComponentEvent e){} public void componentShown(ComponentEvent e){} public void componentMoved(ComponentEvent e){}
    public void componentResized(ComponentEvent e)
    {
        numberOfDisplayedItems = (int)((getHeight() / itemHeight) + 0.5);
        repaint();
    }

    public void mouseWheelMoved(MouseWheelEvent e)
    {
        if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL)
        {
            if (e.getUnitsToScroll() > 0)
            {
            viewedHeight += itemHeight;
            }else{
            viewedHeight -= itemHeight;
            }

            if (viewedHeight > (data.size() * itemHeight) - getHeight())
                viewedHeight = (data.size() * itemHeight) - getHeight();

            if (viewedHeight < 0)
            {
                viewedHeight = 0;
            }

            mouseMoved((MouseEvent)e);

            repaint();
        }
    }

    public void mouseMoved(MouseEvent e)
    {
        int mouseHeight = viewedHeight + e.getY();
        int ID = mouseHeight / itemHeight;
        mousedIndex = ID;
        repaint();
    }

    public void mouseExited(MouseEvent e)
    {
        mousedIndex = -1;
        repaint();
    }
}

谢谢,如果您在我的编程中发现任何其他明显问题,请随时告诉我:P

Thanks, and if you find any other glaring issues in my programming, please don't hesitate to tell me :P

推荐答案

最直接的问题——在 ListBox 中绘制工件——是由于不遵守 不透明属性.使用 true 承诺绘制所有位,但您的 paintComponent() 没有这样做.

The immediate problem—painting artifacts in ListBox—is caused by not honoring the opaque property. Using true promises to paint all of the bits, but your paintComponent() fails to do so.

这里还有一些建议:

  1. 不要忽视事件调度线程.

一定要使用事件监听器,但也考虑可用的适配器,它们具有方便的 null 实现.

Do use event listeners, but also consider the available adapters, which have convenient null implementations.

不要重新发明现有组件,并仅作为最后的手段覆盖 paintComponent().

Don't reinvent existing components, and override paintComponent() only as a last resort.

一定要学会使用布局管理器边框.

是的,有很多东西要学,但这种实验是无价的.

Yes there is much to learn, but this kind of experimentation is invaluable.

这篇关于Swing 组件在彼此内部绘制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆