JAVA设置新视口,java – 在JScrollPane的视口上绘制静态图像

我试图在JScrollPane上绘制一个红色正方形.我下面的代码对此做了一个很好的工作,但有时当我滚动视口太快时,红色方块向上或向下跳跃.

这让我觉得奇怪,因为JScrollPane本身是静止的,所以我假设Swing不会试图移动其中绘制的组件.我猜测实际发生的是红色方块与视口相关联,视口显示移动的图形.

无论如何,如何阻止红色方块跳跃并在列表上成功绘制红色方块?也许我完全采取了错误的做法.

package components;

import java.awt.*;

import java.util.Vector;

import javax.swing.*;

import javax.swing.event.*;

@SuppressWarnings("serial")

public class DialogWithScrollPane extends JFrame {

public DialogWithScrollPane() {

super();

setResizable(false);

Container pane = getContentPane();

Vector listOfStuff = new Vector();

for (int i = 0; i < 100; i++) {

listOfStuff.add(Integer.toString(i));

}

final JScrollPane scrollPane = new JScrollPane() {

public void paint(Graphics g) {

System.out.println("JScrollPane.paint() called.");

super.paint(g);

g.setColor(Color.red);

g.fillRect(20, 50, 100, 200);

}

};

JList list = new JList(listOfStuff) {

public void paint(Graphics g) {

System.out.println("JList.paint() called.");

super.paint(g);

// Well, I could do this...

//

// scrollPane.repaint();

//

// ...and it would solve the problem, but it would also result in an

// infinite recursion since JScrollPane.paint() would call this

// function again.

}

};

// Repaint the JScrollPane any time the viewport is moved or an item in the

// list is selected.

scrollPane.getViewport().addChangeListener(new ChangeListener() {

public void stateChanged(ChangeEvent e) {

scrollPane.repaint();

}

});

list.addListSelectionListener(new ListSelectionListener() {

public void valueChanged(ListSelectionEvent e) {

scrollPane.repaint();

}

});

scrollPane.setViewportView(list);

pane.add(scrollPane);

setMinimumSize(new Dimension(300, 300));

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setLocation(500, 250);

setVisible(true);

}

public static void main(String[] args) {

javax.swing.SwingUtilities.invokeLater(new Runnable() {

public void run() {

new DialogWithScrollPane();

}

});

}

}

解决方法:

JScrollPane应该在JViewport后面绘制,它应该在列表后面绘制.我猜这只是工作,因为你重写了paint而不是paintComponent,并且一直在JScrollPane上调用repaint,以便在绘制组件后再次绘制自己.

也许您想要使用JLayeredPane并让它持有JScrollPane并在其上绘制.

编辑:或玻璃窗,我现在看到mre建议,但我担心如果你这样做,并设置玻璃窗可见,你将失去与底层滚动窗格交互的能力.

编辑2

例如,

import java.awt.*;

import java.awt.event.ComponentAdapter;

import java.awt.event.ComponentEvent;

import java.util.Vector;

import javax.swing.*;

@SuppressWarnings("serial")

public class DialogWithScrollPane2 extends JFrame {

public DialogWithScrollPane2() {

super();

//setResizable(false);

final JPanel pane = (JPanel) getContentPane();

Vector listOfStuff = new Vector();

for (int i = 0; i < 100; i++) {

listOfStuff.add(Integer.toString(i));

}

final JScrollPane scrollPane = new JScrollPane();

JList list = new JList(listOfStuff);

scrollPane.setViewportView(list);

final JPanel blueRectPanel = new JPanel() {

@Override

protected void paintComponent(Graphics g) {

super.paintComponent(g);

g.setColor(Color.blue);

g.fillRect(20, 50, 100, 200);

}

};

blueRectPanel.setOpaque(false);

final JLayeredPane layeredPane = new JLayeredPane();

layeredPane.add(scrollPane, JLayeredPane.DEFAULT_LAYER);

layeredPane.add(blueRectPanel, JLayeredPane.PALETTE_LAYER);

layeredPane.addComponentListener(new ComponentAdapter() {

private void resizeLayers() {

final JViewport viewport = scrollPane.getViewport();

scrollPane.setBounds(layeredPane.getBounds());

blueRectPanel.setBounds(viewport.getBounds());

SwingUtilities.invokeLater(new Runnable() {

public void run() {

blueRectPanel.setBounds(viewport.getBounds());

}

});

}

@Override

public void componentShown(ComponentEvent e) {

resizeLayers();

}

@Override

public void componentResized(ComponentEvent e) {

resizeLayers();

}

});

pane.add(layeredPane);

setPreferredSize(new Dimension(300, 300));

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

pack();

setLocation(500, 250);

setVisible(true);

}

public static void main(String[] args) {

javax.swing.SwingUtilities.invokeLater(new Runnable() {

public void run() {

new DialogWithScrollPane2();

}

});

}

}

标签:java,swing,jscrollpane

来源: https://codeday.me/bug/20190530/1186322.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值