Качаем компоненты, рисуя друг друга - PullRequest
1 голос
/ 26 марта 2011

Это мой четвертый вопрос здесь, примерно через две недели ... Я думаю, мне есть чему поучиться.

В любом случае, я надеюсь, что образец, который я подготовил ниже, объяснит проблему лучше, чем я, но, поскольку я изменил все свои компоненты на 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 ]

3 голосов
/ 27 марта 2011

Непосредственная проблема - рисование артефактов в ListBox - вызвана несоблюдением непрозрачного свойства . Использование true обещает раскрасить все биты, но ваш paintComponent() не может это сделать.

Вот еще несколько предложений:

  1. Не пренебрегайте потоком отправки событий .

  2. Используйте прослушиватели событий , но также учитывайте доступные адаптеры, которые имеют удобную реализацию null.

  3. Не переизобретать существующих компонентов , а переопределять paintComponent() только в качестве крайней меры.

  4. Научитесь использовать Диспетчеры макетов и Границы .

Да, есть чему поучиться, но такие эксперименты неоценимы.

1 голос
/ 26 марта 2011

Вы должны вызывать setVisible(true); только после того, как настроите компонент, в конце вашего конструктора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...