Java 透明JPanel
我正在编写一个GUI,它允许用户绘制一个图形,其中每个节点都由一个扩展的jlabel表示,每个箭头都应该由一个扩展的Jpanel表示,带有透明背景setOpaquefalse,但我注意到只有第一个箭头面板被绘制或至少可见,而其他面板没有显示。此外,在第一个箭头之后添加的节点没有正确绘制:只有当我用鼠标经过它们时,才会绘制它们。所有元素都添加到带有空布局管理器的JPanel中。我知道如果我使用JLayeredPane可能是最好的,但我想知道是否还有其他解决方案。 编辑:以下是我使用的类: 这是表示节点的类Java 透明JPanel,java,swing,jpanel,transparent,translucency,Java,Swing,Jpanel,Transparent,Translucency,我正在编写一个GUI,它允许用户绘制一个图形,其中每个节点都由一个扩展的jlabel表示,每个箭头都应该由一个扩展的Jpanel表示,带有透明背景setOpaquefalse,但我注意到只有第一个箭头面板被绘制或至少可见,而其他面板没有显示。此外,在第一个箭头之后添加的节点没有正确绘制:只有当我用鼠标经过它们时,才会绘制它们。所有元素都添加到带有空布局管理器的JPanel中。我知道如果我使用JLayeredPane可能是最好的,但我想知道是否还有其他解决方案。 编辑:以下是我使用的类: 这是表示
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Iterator;
import java.util.LinkedList;
import javax.swing.JLabel;
import se.diag.exc.EccezioneDaMostrare;
public class AreaNodo extends JLabel implements MouseListener,
MouseMotionListener, Cloneable {
/**
*
*/
private static final long serialVersionUID = 1L;
protected boolean inCreazione;
protected Dimension size=new Dimension(100,40);
protected ObservableArea oss;
protected LinkedList<PannelloFreccia> collegamenti=new LinkedList<PannelloFreccia>();
protected LinkedList<EventoAreaListener> listeners=new LinkedList<EventoAreaListener>();
public AreaNodo(){
super();
setOpaque(true);
addMouseListener(this);
addMouseMotionListener(this);
oss=new ObservableArea(this);
inCreazione=true;
}
public AreaNodo clone(){
AreaNodo areaClonata=new AreaNodo();
areaClonata.setSize(this.size);
Iterator<PannelloFreccia> i=collegamenti.iterator();
while(i.hasNext()){
areaClonata.aggiungiColl(i.next().clone());
}
Iterator<EventoAreaListener> i2=listeners.iterator();
while(i2.hasNext()){
areaClonata.addEventoAreaListener(i2.next());
}
return areaClonata;
}
public void setSize(Dimension d){
size=new Dimension(d.width, d.height);
}
public void setInCreazione(boolean value){
inCreazione=value;
}
public void addEventoAreaListener(EventoAreaListener l){
if (!listeners.contains(l))
listeners.add(l);
}
public void removeEventoAreaListener(EventoAreaListener l){
listeners.remove(l);
}
public void lanciaEventoAreaFineCreazione(){
EventoArea e=new EventoArea(this, MotivazioneEvento.FINE_CREAZIONE);
Iterator<EventoAreaListener> i=listeners.iterator();
while(i.hasNext())
i.next().EventoAreaOccurred(e);
}
public void lanciaEventoAreaSelezionata(){
EventoArea e=new EventoArea(this, MotivazioneEvento.SELEZIONE);
System.out.println("lanciato evento area sel "+this.getText()+" "+this.getToolTipText());
Iterator<EventoAreaListener> i=listeners.iterator();
System.out.println(listeners.size());
while(i.hasNext()){
EventoAreaListener l=i.next();
l.EventoAreaOccurred(e);
System.out.println(l.toString());
}
}
public void aggiungiColl(PannelloFreccia pf){
collegamenti.add(pf);
}
public void removeSubscriber(AreaSubscriber a){
oss.removeSubscriber(a);
}
public void addSubscriber(AreaSubscriber a){
oss.addSubscriber(a);
}
public void aggiungiCollegamento(AreaNodo a) throws EccezioneDaMostrare{
PannelloFreccia p=new PannelloFreccia(getParent().getSize(), this, a);
System.out.println("chiamato aggiungiColl area");
ControllerGUI.aggiungiCollegamento(this, a);
getParent().add(p);
p.setBounds(0,0,getParent().getWidth(), getParent().getHeight());
p.paintImmediately(0,0,p.getWidth(), p.getHeight());
aggiungiColl(p);
a.aggiungiColl(p);
}
public Dimension getMinimumSize(){
return size;
}
public Dimension getPreferredSize(){
return size;
}
public Dimension getSize(){
return size;
}
private void sposta(Point p){
Point pNuovo=new Point(p.x+getLocation().x, p.y+getLocation().y);
setLocation(pNuovo);
}
public void spostaAssoluto(Point p){
setLocation(p);
}
@Override
public void mouseDragged(MouseEvent arg0) {
Point p=arg0.getPoint();
sposta(p);
oss.notifica();
}
@Override
public void mouseMoved(MouseEvent arg0) {
/*if(inCreazione){
Point p=arg0.getPoint();
sposta(p);
oss.notifica();
repaint();
}
*/
}
@Override
public void mouseClicked(MouseEvent arg0) {
if(inCreazione){
inCreazione=false;
lanciaEventoAreaFineCreazione();
}
else
lanciaEventoAreaSelezionata();
}
@Override
public void mouseEntered(MouseEvent arg0) {
Font f=getFont();
f=f.deriveFont(1);
this.setFont(f);
}
@Override
public void mouseExited(MouseEvent arg0) {
Font f=getFont();
f=f.deriveFont(0);
this.setFont(f);
}
@Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public Point getPuntoCollegamento(AreaNodo a){
Point posA=a.getLocation();
if(posA.x>getLocation().x+this.getWidth()){
return(new Point(getLocation().x+getWidth(), getLocation().y+getHeight()/2));
}
else{
if(posA.x>getLocation().x){
if(posA.y<getLocation().y){
return(new Point(getLocation().x+getWidth()/2, getLocation().y));
}
else
return(new Point(getLocation().x+getWidth()/2, getLocation().y+getHeight()));
}
else{
return (new Point(getLocation().x, getLocation().y+getHeight()/2));
}
}
}
public PannelloFreccia ricercaCollegamento(AreaNodo a){
Iterator<PannelloFreccia> i=collegamenti.iterator();
while(i.hasNext()){
PannelloFreccia cur=i.next();
if(cur.getArea2()==a || cur.getArea1()==a)
return cur;
}
return null;
}
protected void rimuoviFreccia(PannelloFreccia p){
collegamenti.remove(p);
}
public void svuota(){
Iterator<PannelloFreccia> i=collegamenti.iterator();
while(i.hasNext()){
PannelloFreccia p=i.next();
p.rimuoviDaSubscriber();
if(p.getArea2()!=this){
p.getArea2().cancellaCollegamento(this);
rimuoviFreccia(p);
}
else{
p.getArea1().cancellaCollegamento(this);
rimuoviFreccia(p);
}
}
listeners=new LinkedList<EventoAreaListener>();
}
public void cancellaCollegamento(AreaNodo a){
PannelloFreccia p=ricercaCollegamento(a);
if(p!=null){
p.rimuoviDaSubscriber();
rimuoviFreccia(p);
}
}
public int hashCode(){
return getText().hashCode();
}
public boolean equals(Object o){
if(o==this) return true;
if(!(o instanceof AreaNodo)) return false;
AreaNodo a=(AreaNodo)o;
return this.getText().equals(a.getText());
}
public Color getColoreNonSel(){
return Color.WHITE;
}
}
这是JPanel,我在这里添加了所有这些
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.LinkedList;
import javax.swing.JPanel;
import se.diag.control.clientspec.grafica.AreaNodo;
import se.diag.control.clientspec.grafica.AreaNodoO;
import se.diag.control.clientspec.grafica.ControllerGUI;
import se.diag.control.clientspec.grafica.EventoArea;
import se.diag.control.clientspec.grafica.EventoAreaListener;
import se.diag.control.clientspec.grafica.MotivazioneEvento;
import se.diag.control.clientspec.grafica.ObserverStato;
import se.diag.control.clientspec.grafica.PannelloDiagnosi;
public class PannelloInserim extends JPanel implements PannelloOp, PannelloDiagnosi, MouseMotionListener {
private boolean inCreazione=false;
private AreaNodo areaDaAggiungere=null;
private Selezione sel;
private ObserverStato btnDiag;
public PannelloInserim(ObserverStato btnDiag) {
super();
setLayout(null);
setBackground(Color.WHITE);
addMouseListener(this);
addMouseMotionListener(this);
ControllerGUI.addEventoAreaListener(this);
sel=new Selezione();
this.btnDiag=btnDiag;
}
public LinkedList<AreaNodo> getSelezione(){
return sel;
}
public void setInCreazione(boolean value){
inCreazione=value;
}
@Override
public void EventoAreaOccurred(EventoArea e) {
AreaNodo a=(AreaNodo)e.getSource();
MotivazioneEvento m=e.getMotivo();
switch(m){
case CREAZIONE:{
areaDaAggiungere=a;
setInCreazione(true);
}
break;
case ELIMINAZIONE:{
a.svuota();
remove(a);
}
break;
case FINE_CREAZIONE:{
setInCreazione(false);
}
}
}
@Override
public void mouseClicked(MouseEvent arg0) {
sel.svuota();
}
@Override
public void mouseEntered(MouseEvent arg0) {
if(inCreazione){
add(areaDaAggiungere);
areaDaAggiungere.setBounds(arg0.getX(), arg0.getY(), areaDaAggiungere.getSize().width, areaDaAggiungere.getSize().height);
areaDaAggiungere.setInCreazione(true);
areaDaAggiungere.addEventoAreaListener(this);
areaDaAggiungere.addEventoAreaListener(sel);
if(areaDaAggiungere instanceof AreaNodoO){
((AreaNodoO)areaDaAggiungere).addObserverStato(btnDiag);
}
}
}
@Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public PannelloMostraDiagnosi mostraDiagnosi() {
return new PannelloMostraDiagnosi(this);
}
@Override
public void mouseDragged(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseMoved(MouseEvent arg0) {
if(inCreazione){
areaDaAggiungere.spostaAssoluto(arg0.getPoint());
}
}
}
这就是此次活动的动机:
package se.diag.control.clientspec.grafica;
public enum MotivazioneEvento {
CREAZIONE{
public String toString(){
return "Area creata";
}
},
SELEZIONE{
public String toString(){
return "Area selezionata";
}
},
ELIMINAZIONE{
public String toString(){
return "Area eliminata";
}
},
FINE_CREAZIONE{
public String toString(){
return "Fine Creazione";
}
}
}
这是EventoArea侦听器的接口:
package se.diag.control.clientspec.grafica;
import java.util.EventListener;
public interface EventoAreaListener extends EventListener {
public void EventoAreaOccurred(EventoArea e);
}
这是一个类,用于带有箭头面板的观察者模式,以使它们跟随节点:
package se.diag.control.clientspec.grafica;
import java.util.LinkedList;
public class ObservableArea {
private LinkedList<AreaSubscriber> sub;
private AreaNodo area;
public ObservableArea(AreaNodo a){
area=a;
sub=new LinkedList<AreaSubscriber>();
}
public void notifica(){
for(AreaSubscriber elem:sub)
elem.update(area);
}
public void addSubscriber(AreaSubscriber a){
sub.add(a);
}
public void removeSubscriber(AreaSubscriber a){
sub.remove(a);
}
}
当两个节点之间没有链接的节点被选中时,Selezione调用AggiungCollegamento,这将创建一个新的箭头面板并将其添加到PanneLoinserim 没关系,我发现了问题:在arrow面板的paintComponent方法中调用了clearRect。删除该行后,箭头变为可见,其他组件也没有问题 如果你发布一个.我自己,我会直接在主绘图JPanel的paintComponent方法中创建箭头,而不是在各自的JPanel中创建箭头。@HoverCraftfullOfels,这是我在编写箭头代码时考虑的解决方案之一,但我更喜欢将每个箭头放在不同的对象中,以简化添加,删除和移动节点以及连接节点的箭头。这段代码不是有点太长了,不能指望人们调试它吗?正如已经指出的,使用SSCCE您可能会有更好的运气。@Orgrim:别误会,我同意箭头应该是它们自己的类,但它们可以更像一个逻辑类,而不是一个可视化组件类,并且不必从JComponent扩展。主绘图面板可以保存箭头对象的集合,并可以在paintComponent中遍历集合,告知每个对象自行绘制。这有助于将逻辑与视图分离。
package se.diag.control.clientspec.grafica;
public enum MotivazioneEvento {
CREAZIONE{
public String toString(){
return "Area creata";
}
},
SELEZIONE{
public String toString(){
return "Area selezionata";
}
},
ELIMINAZIONE{
public String toString(){
return "Area eliminata";
}
},
FINE_CREAZIONE{
public String toString(){
return "Fine Creazione";
}
}
}
package se.diag.control.clientspec.grafica;
import java.util.EventListener;
public interface EventoAreaListener extends EventListener {
public void EventoAreaOccurred(EventoArea e);
}
package se.diag.control.clientspec.grafica;
import java.util.LinkedList;
public class ObservableArea {
private LinkedList<AreaSubscriber> sub;
private AreaNodo area;
public ObservableArea(AreaNodo a){
area=a;
sub=new LinkedList<AreaSubscriber>();
}
public void notifica(){
for(AreaSubscriber elem:sub)
elem.update(area);
}
public void addSubscriber(AreaSubscriber a){
sub.add(a);
}
public void removeSubscriber(AreaSubscriber a){
sub.remove(a);
}
}
package se.diag.control.clientspec.grafica;
public interface AreaSubscriber {
public void update(AreaNodo a);
}