在另一个组件中绘制外来组件(即属于不同框架的内容窗格) [英] Paint foreign component (i.e. belonging to a different frame's content pane) in another component

查看:167
本文介绍了在另一个组件中绘制外来组件(即属于不同框架的内容窗格)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好。
我想绘制一个外来组件(即属于不同框架的内容窗格),我们称之为框架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;

公共类PaintForeignComponentSSCCE扩展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));
//绘制外部面板的组件
ForeignComponentPainter fcp = new ForeignComponentPainter(fp);
fcp.setPreferredSize(new Dimension(600,600));
//主框架的内容
JPanel contentPane = new JPanel();
contentPane.setBackground(Color.BLUE);
contentPane.add(fcp);
//主框架
JFrame f = new PaintForeignComponentSSCCE();
f.setContentPane(contentPane);
f.setSize(700,500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
//外国小组框架
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扩展JButton
{
private static final long serialVersionUID = 1L;
私人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())
返回NO_SUCH_PAGE;
int savedPage = currentPageIndex;
currentPageIndex = pageIndex;
Graphics2D g2 =(Graphics2D)g;
paint(g2);
currentPageIndex = savedPage;
返回PAGE_EXISTS;
}


解决方案

抱歉,我不能直接解决您的问题,但可以通过拥有共同模型的两个不同视图来避免它。如 如何编写文档监听器所示,可以更新多个查看 文档。您的模型和视图可能会有所不同,但概念仍然适用。



附录:


我认为这就是我现在正在做的事情,不是吗?我有一个模型,即'外国'组件,两个视图一个做默认油漆和第二个自定义油漆。


不,你有一个视图更新另一个;你需要两个视图来响应一个模型。这个相关的示例可能会提供一些见解。


我仍然对这个错误绘画的原因提出建议感兴趣。


尝试交错两个组件的更新是,IMO,从根本上是有缺陷的;它颠覆了 绘画在摇摆中的正常过程 。在我的平台上,我只看到一个非常短暂的闪烁,没有不定的绘画。虽然有可能在一个系统上获得满意的结果,但这种安排在不同的实现中都是不可靠的。


是一个简单的重新调用标签,放在 ModelObserver update()方法中的相应解决方案?


是, repaint(),但应该在 ButtonHandler 查看

 私有类ButtonHandler实现ActionListener {

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


Hallo all. I want to paint a foreign component (i.e. belonging to a different frame's content pane), lets call it frame B, inside a component in frame A.

The problem is that when I paint the component it is painted also in the content pane of the frame A, also it flickers or all gets ugly when the frame is re-sized (i.e. painted few times inside the component, some blue squares are appearing, etc.). The issue becomes more visible if I try to, for example, scale or translate the foreign component before painting.

After a while I sorted it, I think. But I do not feel good with this solution, for some reason I believe there might be a better one, a more appropriate one. Here I need you. :)

This question is more a call for an explanation why the foreign component is painted incorrectly without manipulating it's double buffering feature before and after the paint inside the component. For example with use of either pair of setDoubleBuffered(false) and setDoubleBuffered(true) or disableDoubleBuffering(jP) and enableDoubleBuffering(jP)

respectively before and after the call to the foreign component's paint method.

Thank You in advance. The SSCCE showing the problem is presented below.


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);
    }
}

Not related to the SSCCE example. The below is unrelated to the problem itself. This piece of code serves the purpose of presentation of how I am implementing Printable in the component which I also want to render in a print preview fashion. The print calls paint of the component (as shown below).


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; 
} 

解决方案

Sorry, I can't address your question directly, but it may be possible to avoid it by having two different views of a common model. As shown in How to Write a Document Listener, it is possible to update more than one view of a Document. Your model and view(s) might be different, but the concept would still apply.

Addendum:

I think that is what I am doing at the moment, isn't it? I have one model i.e. the 'foreign' component, and two views one doing default paint and second custom paint.

No, you have one view updating another; you need two views responding to one model. This related example may offer some insight.

I am still interested in suggestions as to the reasons of this erroneous painting.

The attempt to interleave the updates of two components is, IMO, fundamentally flawed; it subverts the normal process of Painting in Swing. On my platform, I see only a very brief flicker and no adventitious painting. Although it may be possible to obtain satisfactory results on one system, the arrangement would be unreliable across implementations.

Is a simple call to repaint of the label, placed in the ModelObserver's update() method the appropriate solution?

Yes, repaint(), but it should be done in the ButtonHandler for 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);
    }
}

这篇关于在另一个组件中绘制外来组件(即属于不同框架的内容窗格)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆