Рисование стороннего компонента (т. Е. Принадлежащего к другой области содержимого фрейма) в другом компоненте - PullRequest
1 голос
/ 11 марта 2011

Привет всем.Я хочу нарисовать сторонний компонент (т.е. принадлежащий другой области содержимого фрейма), назовем его фреймом B внутри компонента в фрейме A.

Проблема в том, что когда я рисуюкомпонент, который он окрашивает также на панели содержимого кадра A, также мерцает или все становится уродливым при изменении размера рамки (т. е. окрашивается несколько раз внутри компонента, появляются синие квадраты и т. д.).Проблема становится более заметной, если я попытаюсь, например, масштабировать или перевести внешний компонент перед рисованием.

Через некоторое время, я думаю, я это отсортировал.Но я не чувствую себя хорошо с этим решением, по некоторым причинам я полагаю, что могло бы быть лучшее, более подходящее.Здесь ты мне нужен.:)

Этот вопрос больше напоминает объяснение того, почему внешний компонент нарисован неправильно, не манипулируя его функцией двойной буферизации до и после рисования внутри компонента.Например, с использованием пары setDoubleBuffered (false) и setDoubleBuffered (true) или disableDoubleBuffering (jP) и enableDoubleBuffering (jP)

соответственно до и после вызова метода рисования внешнего компонента.

Спасибо заранее.SSCCE, показывающий проблему, представлен ниже.


import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.RepaintManager;

public class PaintForeignComponentSSCCE extends JFrame
{
    public static void main(String[] args) throws IOException
    {
        //foreign panel
        JPanel fp = new JPanel();
        fp.setBackground(Color.PINK);
        fp.setPreferredSize(new Dimension(200, 300));
        //component in which the foreign panel is painted
        ForeignComponentPainter fcp = new ForeignComponentPainter(fp);
        fcp.setPreferredSize(new Dimension(600, 600));
        //main frame's content
        JPanel contentPane = new JPanel();
        contentPane.setBackground(Color.BLUE);
        contentPane.add(fcp);
        //main frame
        JFrame f = new PaintForeignComponentSSCCE();
        f.setContentPane(contentPane);
        f.setSize(700, 500);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);             
        //foreign panel frame
        JFrame fpf = new JFrame();
        JPanel panelFrameContent = new JPanel();
        panelFrameContent.add(fp);
        fpf.setContentPane(panelFrameContent);
        fpf.setSize(400, 400);
        fpf.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        fpf.setVisible(true);
    }
}

class ForeignComponentPainter extends JButton
{
    private static final long serialVersionUID = 1L;
    private JPanel jP;

    public ForeignComponentPainter(JPanel jP)
    {
        super();
        this.jP = jP;
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.drawString("OIOI", 50, 50);
        //g2.translate(100, 50);
        //g2.scale(.5, .5);
//      jP.setDoubleBuffered(false);
//      disableDoubleBuffering(jP);
        jP.paint(g2);
//      jP.setDoubleBuffered(true);
//      enableDoubleBuffering(jP);
        //g2.scale(1/.5, 1/.5);
    }   
    public static void disableDoubleBuffering(Component c)
    {
        RepaintManager currentManager = RepaintManager.currentManager(c);
        currentManager.setDoubleBufferingEnabled(false);
    }
    public static void enableDoubleBuffering(Component c)
    {
        RepaintManager currentManager = RepaintManager.currentManager(c);
        currentManager.setDoubleBufferingEnabled(true);
    }
}

Не относится к примеру SSCCE. Нижеприведенное не связано с самой проблемой. Этот фрагмент кодаслужит для представления того, как я реализую Printable в компоненте, который я также хочу визуализировать в режиме предварительного просмотра.Печать вызывает рисование компонента (как показано ниже).


public int print(Graphics g, PageFormat pageFormat, int pageIndex)
{ 
   if(pageIndex >= pageHeights.size()) 
      return NO_SUCH_PAGE; 
   int savedPage = currentPageIndex; 
   currentPageIndex = pageIndex; 
   Graphics2D g2 = (Graphics2D) g; 
   paint(g2); 
   currentPageIndex = savedPage; 
   return PAGE_EXISTS; 
} 

1 Ответ

2 голосов
/ 11 марта 2011

Извините, я не могу ответить на ваш вопрос напрямую, но можно избежать его, имея два разных взгляда на общую модель. Как показано в Как написать прослушиватель документов , можно обновить более одного представления из Document. Ваша модель и представления могут отличаться, но концепция все равно будет применяться.

Приложение:

Я думаю, это то, чем я сейчас занимаюсь, не так ли? У меня есть одна модель, то есть «чужой» компонент, и два вида, один из которых выполняет рисование по умолчанию, а второй - произвольный.

Нет, у вас есть один вид, обновляющий другой; вам нужно два представления, отвечающие одной модели. Этот связанный пример может дать некоторое представление.

Меня все еще интересуют предложения относительно причин этой ошибочной картины.

Попытка чередовать обновления двух компонентов, IMO, в корне ошибочна; это подрывает нормальный процесс Живопись в Swing . На моей платформе я вижу только очень короткое мерцание и никакой случайной живописи. Хотя возможно получить удовлетворительные результаты в одной системе, такая компоновка будет ненадежной во всех реализациях.

Является ли простой вызов для перекраски метки, помещенной в метод ModelObserver update(), подходящим решением?

Да, repaint(), но это должно быть сделано в ButtonHandler для View:

private class ButtonHandler implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        PieceButton pb = (PieceButton) e.getSource();
        icon.color = pb.piece.color;
        label.repaint();
        model.check(pb.piece);
    }
}
...