Java updateUI 只工作一次

Chr*_*ris 0 java swing

这是我正在构建的应用程序https://github.com/chrisbramm/LastFM-History-Graph

下面是src/lastfmhistoryclasses. 当OutputGUIView创建它创建三个组成部分,一JPanel graphPanel,这是添加到JScrollPane graphScrollPanel和其他JPanel autocompletePanel。然后这些都被添加到JFrame OutputGUIView. 下面的侦听器会更改首选大小,graphPanel并且在您第一次按下按钮时,UI 会更新以显示graphPanel大小已增加且滚动条graphScrollPanel已更改。

但是,现在,如果您按下另一个按钮,首选大小会发生变化,但 UI 不会更新,如果您通过最大化它来更改窗口尺寸,它会这样做。

class Zoom2000 implements ActionListener{
    public void actionPerformed(ActionEvent e){
        outputGUIView.graphPanel.setPreferredSize(new Dimension(screenWidth, 2000));
        outputGUIView.graphScrollPanel.updateUI();

    }
}
class ZoomDefault implements ActionListener{
    public void actionPerformed(ActionEvent e){
        outputGUIView.graphPanel.setPreferredSize(new Dimension(screenWidth, screenHeight));
        outputGUIView.graphScrollPanel.updateUI();


    }
}
class Zoom6000 implements ActionListener{
    public void actionPerformed(ActionEvent e){
        outputGUIView.graphPanel.setPreferredSize(new  Dimension(screenWidth, 6000));
        outputGUIView.graphScrollPanel.updateUI();

    }
}
Run Code Online (Sandbox Code Playgroud)

我也尝试了不同的东西,例如invalidate/validate/revalidate(和重新绘制)各种组件,而 graphPanel 只是坐在那里,只有在您更改窗口尺寸时才重新绘制。

任何想法我做错了什么?

编辑更新:这是 GraphPanel 类:

package lastfmhistoryguis;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import javax.swing.*;

import de.umass.lastfm.*;
import lastfmhistoryclasses.*;

SuppressWarnings("serial")
public class GraphPanel extends JPanel {

private LastFMHistory graphData;
private int graphHeight;
private int graphWidth;
private int zoom;
private final int PAD = 20;

public GraphPanel(LastFMHistory model, int zoom){
    this.graphData = model;
    if (zoom != 1){
        this.zoom = zoom;
    }else{
        this.zoom = 1;
        System.out.println("getHeight() returning:" + getHeight());
    }
    System.out.println("Width" + getWidth() + "Height" + getHeight());

}

protected void paintComponent(Graphics g) {
    super.paintComponent(g);
     System.out.println("Drawing");
    Graphics2D graph = (Graphics2D) g;

    if (graphData == null) {
        System.err.println("No data found");
    } else {
        System.out.println("paintComponent Width" + getWidth() + "Height" + getHeight());
        graphWidth = getWidth() - 5 * PAD;
        //graphHeight = getHeight() - 2 * PAD;
        graphHeight = 6000 - 2* PAD;
        System.out.println(graphWidth + ", " + graphHeight);

        int x0 = graphWidth + PAD;
        graph.draw(new Rectangle2D.Double(PAD, PAD, graphWidth, graphHeight));
        double xInc = (double) (graphWidth) / (graphData.dayMax);
        double secondHeight = (double) (graphHeight) / 86400;

        for (int i = 0; i <= 86400; i++) {
            if (i % 3600 == 0) {
                graph.draw(new Line2D.Double(x0, (i * secondHeight) + PAD,
                        x0 + 10, (i * secondHeight) + PAD));
                String hour = Integer.toString(i / 3600);
                graph.drawString(hour, x0 + 15,
                        (int) ((i * secondHeight) + PAD));
            }
        }

        for (Track t : graphData.history) {
            if (t.getPlayedWhen() != null) {

                Color color = t.getColour();

                int duration = t.getDuration();
                int day = Math.abs(t.getDay());
                double dayOrigin = x0 - ((day + 1) * xInc);
                double timeOrigin = t.getGraphHeight() * secondHeight + PAD;
                double trackHeight = duration * secondHeight;
                graph.setColor(color);
                // System.out.println("PLOTTING TRACK, " + day + ", " +
                // dayOrigin + ", " + t.getGraphHeight() + ", " + timeOrigin
                // + ", " + trackHeight);
                // graph.draw(new Rectangle2D.Double(dayOrigin, timeOrigin,
                // xInc, trackHeight));
                graph.fillRect((int) dayOrigin, (int) timeOrigin,
                        (int) xInc, (int) trackHeight);
            }

        }

        for (int i = 0; i < graphData.dayMax;){
            graph.draw(new Line2D.Double(x0 - i * xInc, PAD, x0 - i * xInc, graphHeight + PAD));
            i = i + 7;
        }

    }
}
public void zoom(int zoom){
    this.zoom = zoom;
    repaint();
}
Run Code Online (Sandbox Code Playgroud)

}

它创建一个 Graphics2D 对象,在该对象上绘制一个大的轮廓矩形,然后将每个轨道矩形绘制到这个 Graphics2D 图形对象的某处。现在我已经删除了这里推荐的 setPreferredSize 的使用,但是现在我遇到了问题,当我手动将 GraphPanel 中的 graphHeight 设置为 6000 的高度时,graphScrollPanel 没有意识到它包含的 graphPanel 实际上更大,因为所有 graphHeight 是做的是绘制一个约 6000 像素高的矩形。那么在这种情况下我应该使用 setPreferredSize 还是有另一种方法来设置 Graphics2D 对象的大小?

Mad*_*mer 5

不要调用updateUI这与 UI 外观和感觉 API 相关,与重绘关系不大。

您尝试过/正在使用哪些布局管理器?

调用invalidate(),repaint()应该会影响父容器布局管理器并导致它们相应地重新布局组件,但您需要记住,布局管理器仅使用 min/max/pref 大小信息作为指导。

从你的例子中我最好的客人是你应该尝试打电话

outputGUIView.graphPanel.invalidate();
outputGUIView.graphPanel.repaint();
Run Code Online (Sandbox Code Playgroud)

和/或

outputGUIView.invalidate();
outputGUIView.repaint();
Run Code Online (Sandbox Code Playgroud)

在滚动窗格中调用 invalidate 可能不会实现很多,因为视口负责布局内容,而不是滚动窗格。

如果你真的很绝望,你可以试试

outputGUIView.graphScrollPanel.getViewport().invalidate();
outputGUIView.graphScrollPanel.getViewport().repaint();
Run Code Online (Sandbox Code Playgroud)