java - Swing 组件在彼此内部绘制

标签 java swing

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

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

这段代码本质上是我在不完全解决问题的情况下尽可能多地精简了我的程序。我在其中插入了几个自定义列表框组件来演示该问题,并将边框设为红色,以便更容易看到绘制的内容。

测试.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);
    }

}

测试屏幕.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

最佳答案

直接的问题——在 ListBox 中绘制工件——是由于不遵守 opaque property 引起的.使用 true promise 绘制所有位,但您的 paintComponent() 未能这样做。

这里还有一些建议:

  1. 不要忽视 event dispatch thread .

  2. 请使用 event listeners ,还要考虑可用的适配器,它们具有方便的 null 实现。

  3. 不要重新发明 existing components ,并仅在万不得已时才覆盖 paintComponent()

  4. 学习使用 layout managersborders .

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

关于java - Swing 组件在彼此内部绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5444289/

相关文章:

java - Jenkins 使用 Maven 依赖项构建失败

java - 我如何从android中的txt文件中读取特定文本

java - 如何使用 Nimbus Laf 更改内部框架的 "minimize, maximize and close"图标?

javascript - 使用 http 协议(protocol)、java 和 javascript 下载大于 1GB 的大文件

java - 如何使用 JFreeChart 创建 SVG?

java - 第二次触发更新时 OnetoOne 映射的延迟初始化

Java 线程组织指南

java - JTextPane/JTextField 罕见字符的奇怪行为

java - 如何将 2 个独立的 JPanel 添加在一起以获得 1 个 JPanel?

java - 输入键在 JTextArea 中不起作用