2011-03-26 2 views
1

これは約2週間で私の4番目の質問です...私は多くのことを学ぶべきだと思います。スイングコンポーネントが互いに内側に引き込まれています

とにかく、以下に準備したサンプルで問題をよりよく説明できると思っていますが、すべてのコンポーネントをAWTではなくSwingに変更してから、すべてのコンポーネントを私が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

+0

「描画問題」の意味についての説明を追加する必要があります。 –

+0

@Bala:試してみますが、問題の内容を実際には分かりません。 – Tharwen

+0

+1 [sscce](http://sscce.org/)。簡潔にするために、単一のパブリッククラスとそれに続く必要な非パブリッククラス(例:http://stackoverflow.com/questions/3420651)を考えてみましょう。 – trashgod

答えて

3

ListBoxにあるすぐ問題の絵画アーチファクトは、opaque propertyを尊重しないことが原因です。 trueを使用すると、すべてのビットをペイントすることが約束されますが、paintComponent()はそうすることができません。ここで

は、さらにいくつかの提案です:

  1. event dispatch threadを無視しないでください。

  2. event listenersを使用しますが、便利なnull実装を持つ使用可能なアダプタも考慮してください。

  3. existing componentsを再作成して、最後の手段としてpaintComponent()を上書きしないでください。

  4. layout managersおよびbordersを使用することを忘れないでください。

はい、この種の実験は非常に貴重です。

+0

だから私もリストボックスの背景をペイントする必要がありますか? OK。それらの他のものは私をノブのように感じさせます...私は多くの読書をする必要があります。 – Tharwen

+0

'setOpaque(false)'または 'fillRect()'の効果を見てみましょう。 – trashgod

1

setVisible(true);は、コンストラクタの終わりにコンポーネントをセットアップした後でなければなりません。