Java JScrollPane不';t在JSplitPane上更新JScrollBar

Java JScrollPane不';t在JSplitPane上更新JScrollBar,java,image,drawing,jscrollpane,jscrollbar,Java,Image,Drawing,Jscrollpane,Jscrollbar,我想创建一个简单的应用程序,可以编辑图像。应用程序的主视图包含JSplitPane和两个JScrollPane。每个JScrollPane都包含JPanel。右边的JPanel有几个按钮等,左边的JPanel是我的绘图区域 这是我的问题 当我第一次创建jpaneldrawingara时,我可以设置首选大小。如果大小大于JScrollPane的大小,则会显示JScrollBars(默认情况下,大小相等)。但当我将图像加载到jpaneldrawingara滚动条时,滚动条不会更新。尽管我设置了新的首

我想创建一个简单的应用程序,可以编辑图像。应用程序的主视图包含
JSplitPane
和两个
JScrollPane
。每个
JScrollPane
都包含
JPanel
。右边的
JPanel
有几个按钮等,左边的
JPanel
是我的绘图区域

这是我的问题

当我第一次创建
jpaneldrawingara
时,我可以设置首选大小。如果大小大于
JScrollPane
的大小,则会显示
JScrollBars
(默认情况下,大小相等)。但当我将图像加载到
jpaneldrawingara
滚动条时,滚动条不会更新。尽管我设置了新的首选大小
jpaneldrawingara
(大于
JScrollPane
)滚动条,但除非我手动更改
JSplitPanes
分隔器位置,否则滚动条不会更新

这是我的
JSplitPane
自定义类:

public class DrawingPaneView extends JSplitPane{

private DrawingWorkMode drawingWorkMode;
private ImageWorkerView imageWorker;
JScrollPane workScrollPane;
JScrollPane pictureScrollPane;
private DrawingPaneController controller;

private Dimension minimumSize = new Dimension(100, 200);
private JPanel imagePanel;


public DrawingPaneView() {

    setPreferredSize(new Dimension(ConfigClass.APP_WIDTH,ConfigClass.DRAWING_PANE_HEIGHT));
    controller = new DrawingPaneController(this); 

    //Panel
    drawingWorkMode = new DrawingWorkMode();
    workScrollPane = new JScrollPane(drawingWorkMode);

    //Image
    imageWorker = new ImageWorkerView();
    pictureScrollPane = new JScrollPane(imageWorker);


    workScrollPane.setMinimumSize(minimumSize);
    pictureScrollPane.setMinimumSize(minimumSize);


    //addJPanels
    this.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
    this.setRightComponent(workScrollPane);
    this.setLeftComponent(pictureScrollPane);

    //addLeftPanelWithJButtonOnly
    imagePanel = new ImagePanelView();
    pictureScrollPane.setRowHeaderView(imagePanel);

    this.setDividerLocation(ConfigClass.DRAWING_PANE_WIDTH);
    this.setOneTouchExpandable(true);

}

//Change mode
public void changeMode(String mode){
    drawingWorkMode.changeMode(mode);
}      
}
还有我的自定义
JPanel
,它执行绘图:

public class ImageWorkerView extends JPanel {

private BufferedImage img;
private ImageWorkerController controller;
private int defaultBounds = 50;
private double scale=1.0;
int imgW;
int imgH;

public ImageWorkerView() {
    //setLayout(new BorderLayout(0, 0));
    controller = new ImageWorkerController(this);
}


public void setScale(double scale) {
    this.scale = scale;
}

public void setImage(File image) {
    try {
        img = ImageIO.read(image);
        if (img.getType() != BufferedImage.TYPE_INT_RGB) {
            BufferedImage img2 =
                new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);
            Graphics big = img2.getGraphics();
            big.drawImage(img, 0, 0, null);
            img = img2;
        }
    } catch (IOException e) {
        System.out.println("Image could not be read");
    }
}

private void adjustPreferredSize(Boolean defaultSize){

    if(defaultSize){
        //Calculate the proper size of drawing area
        imgW = ConfigClass.DRAWING_PANE_WIDTH - ImagePanelView.PREFERRED_WIDTH-10;
        imgH = ConfigClass.DRAWING_PANE_HEIGHT-50;
        setPreferredSize(new Dimension(imgW,imgH));
        controller.setWindowHeight(imgH);
    }
    else{
        imgW = (int)(img.getWidth() * scale + (defaultBounds*2));
        imgH = (int)(img.getHeight() * scale + (defaultBounds*2));
        setPreferredSize(new Dimension(imgW,imgH));
        controller.setWindowHeight(imgH);
    }   
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;

    if(img!=null){
        if(scale!=1.0){
            AffineTransform at = AffineTransform.getScaleInstance(scale, scale);
            AffineTransformOp aop =
                new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC);
            g2.drawImage(img, aop, defaultBounds, defaultBounds);
        }
        else
            g2.drawImage(img, defaultBounds, defaultBounds, null);
        adjustPreferredSize(false);
    }
    else{
        adjustPreferredSize(true);
    }



}
}
以及如何加载图像:

public class ImageWorkerController {
ImageWorkerView view;
ImageModel model;


public ImageWorkerController(ImageWorkerView workerView) {
    this.view = workerView;
    this.model = ApplicationContext.getObject(ImageModel.class);

    //Load image
    ApplicationContext.getObject(Context.class).addPropertyChangeListener(new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
            if(Context.IMAGE_LOADED.equals(evt.getPropertyName())){
                view.setImage((File) evt.getNewValue());
                view.repaint();
            }
        }
    });

public void setWindowHeight(int h){
    model.setDrawingWindowHeight(h);
}
}

正如您所看到的,当第一次调用
adjustPreferredSize()
方法时,它将
preferredSize
设置为大于
JScrollPane
JScrollBars
出现。但当它再次被调用时,它什么也不做

有趣的是,当我手动更改分隔器的位置
JScrollBars
显示时,下面的屏幕上有一个示例:

所以有某种事件使得
JScrollPane
更新?我尝试过几种方法:
updateUI()
repaint()
revalidate()
。他们都没有工作


你知道我做错了什么吗?

简而言之,你需要
revalidate()
你的
ImageWorkerView
(就在你调用
repaint()
的地方)。这将要求组件及其父级进行“重新布局”,进而触发滚动条的必要调整

谢谢你的回答!你的建议使我深思。实际上我做错的是在
repaint()
之后立即调用
revalidate()
,所以实际上
revalidate()
ImageWorkerView
中的
paintComponent
方法之前执行(我在调试过程中发现了这一点)。正确的方法是:

ApplicationContext.getObject(Context.class).addPropertyChangeListener(new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
            if(Context.IMAGE_LOADED.equals(evt.getPropertyName())){
                view.setImage((File) evt.getNewValue());
                //view.repaint();
                view.paintImmediately(new Rectangle(1, 1));
                view.revalidate();
            }
        }
    });
因此,现在
paintComponent
设置首选大小,然后
revalidate()
调整滚动条