简体   繁体   中英

BorderFactory and Metal L&F issues

I am seeing a strange behaviour. The L&F set is Metal.

UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");

If I set a Border border1 on a JPanel, then I change the Border to border2 on the same JPanel, when a tooltip passes on border2, repaint redraws border1. This occurs on L&F Metal only, with LineBorder, TitledBorder....

happens in Metal L&F only.

You still have a problem even if you don't specifically set the LAF.

If I set a Border border1 on a JPanel, then I change the Border to border2 on the same JPanel, when a tooltip passes on border2, repaint redraws border1

It has nothing to do with the tooltip.

Just click on a couple of squares and then resize the frame, and all the Borders get repainted blue.

The problem is your ColorsBoard class.

You should NOT be overriding the paintComponent() method to create components.

A painting method is only used for painting.

The paintComponent() method is called whenever Swing determines a component needs to be repainted. This is why resizing the frame also causes the problem. You are recreating all the components.

The solution:

  1. Don't override the paintComponent() method!
  2. create all the components in the constructor of your class
  3. Don't use a null layout. Instead use a GridLayout on the panel and just add your squares to the grid.
  4. use setBackground(Color.LIGHT_GRAY) in the constructor to set the background

Also:

  1. get rid of all the synchronized keywords on your methods. They are not needed.
  2. Don't use "==" to compare Objects. Use the equals(...) method.
public class BorderTest {

private JFrame jFrame;
private Container contentPane;
private ColorsBoard colorsBoard;

public BorderTest() {
    super();

    ToolTipManager.sharedInstance().setInitialDelay(10);
    ToolTipManager.sharedInstance().setDismissDelay(1500);
    jFrame = new JFrame();

    contentPane = jFrame.getContentPane();
    contentPane.setLayout(new BorderLayout());

    jFrame.setPreferredSize(new Dimension(700, 500));
    colorsBoard = new ColorsBoard();
    contentPane.add(colorsBoard, BorderLayout.CENTER);

    JLabel label = new JLabel(""
            + "<html>Click two or three small squares. <br/>"
            + "LineBorder's are set. <br/>"
            + "Then pass the tooltips over the red borders. <br/>"
            + "The red LineBorders' are back to blue. <br/>"
            + "This phenomen appears only in Metal L&F. </html>");
    contentPane.add(label, BorderLayout.EAST);

    jFrame.pack();
    jFrame.setVisible(true);
}

public static void main(String[] args) {
     try {
            UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");

        new BorderTest();
    } catch (Exception e) {
            e.printStackTrace();
    }
}
}

class ColorsBoard extends JPanel {

private int squareSize = 315;
private int horizontal = 8;    //number of squares H
private int vertical = 8;      //number of squares V

private SquaredPanel[] squarePanels;   
int index = 0;
public int lastClickedSquare = -1;

// the chess board like JPanel.

public ColorsBoard() {
    squarePanels= new SquaredPanel[horizontal * vertical];
    this.setPreferredSize(new Dimension(squareSize, squareSize));
    setLayout(null);
}

// fill with squares (SquaredPanel)

protected synchronized void paintComponent(Graphics g) {
    super.paintComponent(g);

    int tileSizeH = squareSize / horizontal;
    int tileSizeV = squareSize / vertical;

    g.setColor(Color.LIGHT_GRAY);
    g.fillRect(0, 0, getWidth(), getHeight());

    for(int i = 0; i < horizontal*vertical; i++) {
        squarePanels[i] = new SquaredPanel(this);
    }

    index = 0;
    for (int i = 0; i < horizontal; i++) {
        for (int j = 0; j < vertical; j++) {
                if(index == horizontal * vertical) break;
                    squarePanels[index].setBackground(Color.gray);
                    squarePanels[index].setSize(tileSizeH - 1, tileSizeV - 1);
                    squarePanels[index].setLocation(i * tileSizeH, j * tileSizeV);
                    squarePanels[index].setName("index " + index);
                    squarePanels[index].setIndex(index);
                    add(squarePanels[index]);
                    index++;
            }
        }
    }

public void eraseLastBlueBorder(int lastClickedSquare2) {
    if (lastClickedSquare == -1) {
        lastClickedSquare = lastClickedSquare2;
        return;
    }
    if(!squarePanels[lastClickedSquare].isRed)(squarePanels[lastClickedSquare]).cleanBorder();
    lastClickedSquare = lastClickedSquare2;
}
}

class SquaredPanel extends JPanel {

private String name;
protected Boolean isRed = false;
private int index;
private Border theBorder =  (new LineBorder(Color.gray, 2));

protected Border getTheBorder() {
    return theBorder;
}

public SquaredPanel(ColorsBoard colorsBoard) {
    super();

    addMouseListener(new MouseListener(){
        public void mouseClicked(MouseEvent e) {
        }
        public void mousePressed(MouseEvent e) {
        }
        public void mouseReleased(MouseEvent e) {
            colorsBoard.eraseLastBlueBorder(index);
            setTitleBorder("RED");
        }
        public void mouseEntered(MouseEvent e) {
            setToolTipText(name);
        }
        public void mouseExited(MouseEvent e) {
            setToolTipText(null);
        }
      });
}

// the setBorder call
    protected void setTitleBorder(String title) {
        theBorder = (new LineBorder(title == "BLUE" ? Color.red : Color.blue, 2));
        setBorder(theBorder);
    }


public synchronized void cleanBorder() {
    setTitleBorder("BLUE");
}

public void setName(String name) {
    this.name = name;
}

public void setIndex(int k) {
    index = k;
}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM