Domanda

C'è un pannello in una JFrame chiamato WatchPanel extends JPanel che utilizza un GroupLayout e contiene una WatchListPanel extends JPanel. Il WatchListPanel utilizza un null LayoutManager e contiene diverse istanze di WatchItemPanel extends JPanel. Il WatchItemPanel delinea il contenuto con un GridBagLayout.

Quando carico il telaio e istanziare il WatchPanel, ho pre-caricare la WatchListPanel con tre istanze WatchItemPanel con dati. Questi funzionano bene. Mia implementazione consente questi per essere riordinati trascinando (da qui il layout null), e che funziona pure. Sul WatchPanel è un pulsante per aggiungere un nuovo orologio, che si apre un nuovo pannello nel proprio JFrame cui un orologio può essere aggiunto. Quando si preme il pulsante "Salva" su questo nuovo pannello, si aggiunge il nuovo orologio al WatchPanel, che gocciola giù nella WatchListPanel e chiude il JFrame per l'aggiunta di un nuovo orologio.

Il problema è che quando si aggiunge questo nuovo WatchItemPanel, non ottiene dipinta a meno a ridimensionare il JFrame che contiene il WatchPanel. Riesco a comunicare con esso tramite drag-n-drop. Posso anche trascinare quel pannello specifico - ma è vuota. Nel momento in cui ridimensionare il WatchPanel, appare ed è dipinto in modo corretto.

Ora, ho ignorato il metodo setBounds su WatchListPanel alla chiamata setSize e repaint su ciascuna delle istanze WatchItemPanel nella lista, ma sto chiamando setBounds e repaint sul nuovo WatchItemPanel già come lo aggiungo. Ho provato ad aggiungere le chiamate repaint e invalidate in ogni luogo immaginabile pensare forse ho perso qualcosa, ma senza fortuna. Sono assolutamente aggiunto il WatchItemPanel al WatchListPanel e chiamato setBounds, setVisible(true), e repaint sul nuovo pannello.

Questi sono i metodi addWatch e updatePositions sul WatchListPanel:

public void addWatch(Watch watch) {
    WatchItemPanel watchPanel = new WatchItemPanel(watch);
    synchronized (this.watches) {
        this.watches.add(watch);
    }
    this.watchPanels.put(watch, watchPanel);
    this.add(watchPanel);
    watchPanel.setOpaque(false);
    watchPanel.setForeground(this.getForeground());
    watchPanel.setBackground(this.getBackground());
    watchPanel.setVisible(true);
    watchPanel.setSize(this.getWidth(), WatchItemPanel.PANEL_HEIGHT);
    for (MouseListener l: this.mouseListeners)
        watchPanel.addMouseListener(l);
    for (MouseMotionListener l: this.mouseMotionListeners)
        watchPanel.addMouseMotionListener(l);
    this.updatePositions();
}

private void updatePositions() {
    int count = 0;
    synchronized (this.watches) {
        for (Watch watch: this.watches) {
            if ((this.selectedWatchPanel != null) && (count == this.selectedWatchPanelPosition))
                count++;
            WatchItemPanel panel = this.watchPanels.get(watch);
            if (panel == this.selectedWatchPanel)
                continue;
            panel.setBounds(0, count * WatchItemPanel.PANEL_HEIGHT, this.getWidth(), WatchItemPanel.PANEL_HEIGHT);
            count++;
        }
    }
    if (this.selectedWatchPanel != null)
        this.selectedWatchPanel.setBounds(0, (this.selectedWatchPanelPosition * WatchItemPanel.PANEL_HEIGHT) + this.selectedWatchPanelDragOffset, this.getWidth(), WatchItemPanel.PANEL_HEIGHT);
    this.repaint();
}

E qui sono i metodi setBounds su WatchListPanel:

@Override
public void setBounds(Rectangle r) {
    super.setBounds(r);
    for (WatchItemPanel panel: this.watchPanels.values()) {
        panel.setSize(r.width, WatchItemPanel.PANEL_HEIGHT);
        panel.repaint();
    }
}

@Override
public void setBounds(int x, int y, int width, int height) {
    super.setBounds(x, y, width, height);
    for (WatchItemPanel panel: this.watchPanels.values()) {
        panel.setSize(width, WatchItemPanel.PANEL_HEIGHT);
        panel.repaint();
    }
}

Un altro pezzo di informazione qui - tutti i quattro pannelli vengono dipinte. Ho calpestato paintComponent nel WatchItemPanel e aggiunto un System.out.println e ottenuto questo risultato:

WatchItemPanel[,0,66,366x22,invalid,layout=java.awt.GridBagLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777219,maximumSize=,minimumSize=,preferredSize=]
WatchItemPanel[,0,44,366x22,layout=java.awt.GridBagLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777219,maximumSize=,minimumSize=,preferredSize=]
WatchItemPanel[,0,22,366x22,layout=java.awt.GridBagLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777219,maximumSize=,minimumSize=,preferredSize=]
WatchItemPanel[,0,0,366x22,layout=java.awt.GridBagLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777219,maximumSize=,minimumSize=,preferredSize=]

Da quella colonna in più "non valido" lì nel pannello? Quando ho ridimensionare il WatchPanel il "non valido" va via. Sembra una colonna in più, però. Non c'è alcun corrispondente valore non valido sulle altre linee. (Questo è l'output predefinito JPanel.toString() con il nome del pacchetto rimosso.

È stato utile?

Soluzione

Dopo aver aggiunto il componente, chiamata this.revalidate(). Ciò fa sì che il contenitore da marcare componenti ri-layout sua. Una volta che si aggiunge questa riga di codice, funziona perfettamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top