摆动组件互相吸引

时间:2011-03-26 18:20:41

标签: java swing

这是我在大约两周内的第四个问题......我想我还有很多需要学习的地方。

无论如何,我希望我在下面准备的样本能够比我更好地解释问题,但是因为我将所有组件都改为Swing而不是AWT,所以他们都在绘制面板中的每个组件每当我打电话给repaint()时,我自己都会在里面。

这段代码基本上是我的程序,尽可能地删除,而不会完全破坏问题。我在那里贴了几个自定义列表框组件来演示这个问题,并使边框变红,以便更容易看到在哪里绘图。

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

2 个答案:

答案 0 :(得分:3)

ListBox中的直接问题 - 绘画工件 - 是由于不尊重opaque property造成的。使用true promises绘制所有位,但paintComponent()未能这样做。

以下是一些建议:

  1. 不要忽视event dispatch thread

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

  3. 请勿重新发明existing components,并仅作为最后手段覆盖paintComponent()

  4. 请务必使用layout managersborders

  5. 是的,有很多值得学习的东西,但这种实验非常宝贵。

答案 1 :(得分:1)

只有在构造函数结束时设置组件后,才应调用setVisible(true);