我正在编写一个GUI,允许用户绘制图形,其中每个节点由扩展的jlabel表示,每个箭头应由具有透明背景的扩展Jpanel表示(setOpaque(false)),但我注意到了仅绘制(或至少可见)第一个“箭头面板”,而其他未显示。此外,在第一个箭头后添加的节点没有正确绘制:只有当我用鼠标移动它们时它们才会被绘制。所有元素都添加到具有null布局管理器的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;
}
}
虽然这是箭头面板
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
public class PannelloFreccia extends JPanel implements AreaSubscriber {
/**
*
*/
private static final long serialVersionUID = 1L;
Freccia f;
AreaNodo area1;
AreaNodo area2;
public PannelloFreccia(Dimension d, AreaNodo a1, AreaNodo a2){
setPreferredSize(d);
area1=a1;
area2=a2;
aggiungiASubscriber();
f=new Freccia(area1.getPuntoCollegamento(area2), area2.getPuntoCollegamento(area1));
setOpaque(false);
}
@Override
public void update(AreaNodo a) {
if (a==area1){
f=new Freccia(area1.getPuntoCollegamento(area2), area2.getPuntoCollegamento(area1));
}
if(a==area2){
f=new Freccia(area1.getPuntoCollegamento(area2), area2.getPuntoCollegamento(area1));
}
repaint();
}
public AreaNodo getArea2(){
return area2;
}
public AreaNodo getArea1(){
return area1;
}
public void aggiungiASubscriber(){
area1.addSubscriber(this);
area2.addSubscriber(this);
}
public void rimuoviDaSubscriber(){
area1.removeSubscriber(this);
area2.removeSubscriber(this);
}
public void paintComponent(Graphics g){
g.clearRect(0, 0, getWidth(), getHeight());
f.disegna(g);
}
public PannelloFreccia clone(){
PannelloFreccia pannelloClonato=new PannelloFreccia(getPreferredSize(), area1.clone(), area2.clone());
return pannelloClonato;
}
}
这是我添加所有这些的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());
}
}
}
这是表示pannelloInserim
中所选节点的数据结构public class Selezione extends LinkedList<AreaNodo> implements EventoAreaListener {
private SelezionePublisher selPub;
public Selezione(){
super();
selPub=new SelezionePublisher();
}
public void aggiungiObserver(ObserverSelezione os){
selPub.addObserverSelezione(os);
}
public void rimuoviObserver(ObserverSelezione os){
selPub.removeObserverSelezione(os);
}
public boolean add(AreaNodo a){
System.out.println("chiamato add");
System.out.println(this.toString());
if (contains(a)){
remove(a);
System.out.println("rimosso");
}
else
if(size()==2){
svuota();
a.setBackground(a.getColoreNonSel());
System.out.println("svuotata");
}
else{
if(size()==1 && getFirst().ricercaCollegamento(a)==null){
System.out.println("collegamento");
try {
super.add(a);
getFirst().aggiungiCollegamento(getLast());
} catch (EccezioneDaMostrare e) {
JOptionPane.showMessageDialog(get(0).getTopLevelAncestor(), e.getMessage());
}
finally{
svuota();
}
}
else{
System.out.println("aggiunta");
super.add(a);
}
}
selPub.notifica(isVuota(), isSingola(), isDoppia());
return true;
}
private void aggiungi(AreaNodo a){
System.out.println("Aggiungi");
add(a);
}
public void svuota(){
System.out.println("chiamato svuota");
Iterator<AreaNodo> i=iterator();
while (i.hasNext()){
AreaNodo a=i.next();
a.setBackground(a.getColoreNonSel());
i.remove();
}
selPub.notifica(isVuota(), isSingola(), isDoppia());
}
public boolean isVuota(){
return size()==0;
}
public boolean isSingola(){
return size()==1;
}
public boolean isDoppia(){
return size()==2;
}
@Override
public void EventoAreaOccurred(EventoArea e) {
if(e.getMotivo()==MotivazioneEvento.SELEZIONE){
aggiungi((AreaNodo)e.getSource());
System.out.println("evento area "+e.getMotivo().toString());
}
}
public String toString(){
StringBuffer sb=new StringBuffer();
int i=1;
sb.append(this.size()+"\n");
for(AreaNodo a:this){
sb.append(i+" "+a.getText()+" "+a.getToolTipText()+"\n");
i++;
}
return sb.toString();
}
}
这是在创建,删除或选择节点时触发的事件:
package se.diag.control.clientspec.grafica;
import java.util.EventObject;
public class EventoArea extends EventObject {
private MotivazioneEvento motivo;
public EventoArea(Object arg0, MotivazioneEvento m) {
super(arg0);
motivo=m;
}
public MotivazioneEvento getMotivo(){
return motivo;
}
}
这是该活动的动机:
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);
}
这是一个Observer模式中使用箭头面板的类,以使它们跟随节点:
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);
}
当选择了两个没有链接的节点时,Selezione调用aggiungiCollegamento,它创建一个新的箭头面板并将其添加到pannelloInserim。
答案 0 :(得分:0)
没关系,我发现了什么错误:在箭头面板的paintComponent()方法中调用了clearRect()。删除该行后,箭头变为可见,其他组件也没有问题。