我的脑袋变得如此混乱,使用这种从右到左的东西,我甚至不确定问题出在哪里,但实际上,当我设置为右边时,我发现滚动条似乎“不太正确”左方向。我将其归结为一个测试程序,其工作原理如下:
我无法判断哪些位是向后的,哪些位是正确的,但是视口开始位于右上角似乎是模糊的,但左侧的滚动条肯定是不一致的。但是,如果我试图翻转滚动条的渲染,那么条形图本身就不会被绘制,就像Aqua发现我试图以某种方式作弊一样。
AquaScrollBarUI
不包含对isLeftToRight()
的单个调用,但可能滚动条很好,而且窗格本身是错误的?
我认为这是一个Swing错误,所以我可能会报告它,但是这个烂摊子有一个优雅的解决方案吗?我正在写一个自定义的外观和感觉Aqua的子类,所以我可以把这种修复尽可能接近Aqua。
import javax.swing.*;
import java.awt.*;
public class ScrollPaneOrientationTest implements Runnable {
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new ScrollPaneOrientationTest());
}
@Override
public void run() {
JPanel view = new ViewPanel();
JScrollPane scrollPane = new JScrollPane(view);
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.add(scrollPane, BorderLayout.CENTER);
frame.applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private class ViewPanel extends JPanel implements Scrollable {
private static final int SIZE = 1000;
private final Paint paint = new GradientPaint(new Point(0, 0), Color.RED, new Point(SIZE, SIZE), Color.BLUE);
@Override
protected void paintComponent(Graphics g) {
((Graphics2D) g).setPaint(paint);
((Graphics2D) g).fill(new Rectangle(0, 0, SIZE, SIZE));
}
@Override
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(400, 400);
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 8;
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 400;
}
@Override
public boolean getScrollableTracksViewportWidth() {
return false;
}
@Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
}
答案 0 :(得分:0)
这是我最初要解决的问题。如果很长一段时间没有更好的选择,我想我会接受我自己的答案。
public class HaquaScrollPaneUI extends AquaScrollPaneUI {
@NotNull
@SuppressWarnings("UnusedDeclaration") // called via reflection
public static ComponentUI createUI(JComponent component) {
return new HaquaScrollPaneUI();
}
@Override
protected MouseWheelListener createMouseWheelListener() {
return new FixedXYMouseWheelHandler();
}
protected class FixedXYMouseWheelHandler extends XYMouseWheelHandler {
@Override
public void mouseWheelMoved(MouseWheelEvent event) {
if (event.isShiftDown() &&
!scrollpane.getComponentOrientation().isLeftToRight()) {
// fixes mouse wheel over scroll pane
event = new MouseWheelEvent(
event.getComponent(), event.getID(), event.getWhen(),
event.getModifiers(),
event.getX(), event.getY(),
event.getXOnScreen(), event.getYOnScreen(),
event.getClickCount(), event.isPopupTrigger(),
event.getScrollType(),
-event.getScrollAmount(),
-event.getWheelRotation(),
-event.getPreciseWheelRotation());
}
super.mouseWheelMoved(event);
}
}
}
public class HaquaScrollBarUI extends AquaScrollBarUI {
@NotNull
@SuppressWarnings("UnusedDeclaration") // called via reflection
public static ComponentUI createUI(JComponent component) {
return new HaquaScrollBarUI();
}
@Override
public void update(Graphics graphics, JComponent component) {
if (fScrollBar.getOrientation() == Adjustable.HORIZONTAL &&
!fScrollBar.getComponentOrientation().isLeftToRight()) {
// fixes painting direction
Graphics2D graphicsCopy = (Graphics2D) graphics.create();
try {
graphicsCopy.translate(fScrollBar.getWidth() - 1, 0);
graphicsCopy.scale(-1, 1);
super.update(graphicsCopy, component);
} finally {
graphicsCopy.dispose();
}
} else {
super.update(graphics, component);
}
}
@Override
protected TrackListener createTrackListener() {
// fixes mouse behaviour
return new FlippedTrackListener();
}
private class FlippedTrackListener extends TrackListener {
@Override
public void mouseReleased(MouseEvent event) {
super.mouseReleased(flipEvent(event));
}
@Override
public void mousePressed(MouseEvent event) {
super.mousePressed(flipEvent(event));
}
@Override
public void mouseDragged(MouseEvent event) {
super.mouseDragged(flipEvent(event));
}
// These ones aren't used, but I figured it would be sane
// to override them anyway, just in case.
@Override
public void mouseClicked(MouseEvent event) {
super.mouseClicked(flipEvent(event));
}
@Override
public void mouseEntered(MouseEvent event) {
super.mouseEntered(flipEvent(event));
}
@Override
public void mouseExited(MouseEvent event) {
super.mouseExited(flipEvent(event));
}
@Override
public void mouseWheelMoved(MouseWheelEvent event) {
super.mouseWheelMoved(flipEvent(event));
}
@Override
public void mouseMoved(MouseEvent event) {
super.mouseMoved(flipEvent(event));
}
private MouseEvent flipEvent(MouseEvent event) {
if (fScrollBar.getOrientation() == Adjustable.HORIZONTAL &&
!fScrollBar.getComponentOrientation().isLeftToRight()) {
int x = fScrollBar.getWidth() - 1 - event.getX();
int y = event.getY();
Point scrollBarLocationOnScreen = fScrollBar.getLocationOnScreen();
int xOnScreen = x + scrollBarLocationOnScreen.x;
int yOnScreen = y + scrollBarLocationOnScreen.y;
return new MouseEvent(
event.getComponent(), event.getID(), event.getWhen(),
event.getModifiersEx(),
x, y, xOnScreen, yOnScreen,
event.getClickCount(), event.isPopupTrigger(), event.getButton());
} else {
return event;
}
}
private MouseWheelEvent flipEvent(MouseWheelEvent event) {
if (fScrollBar.getOrientation() == Adjustable.HORIZONTAL &&
!fScrollBar.getComponentOrientation().isLeftToRight()) {
int x = event.getX();
x = fScrollBar.getWidth() - 1 - x;
int y = event.getY();
Point scrollBarLocationOnScreen = fScrollBar.getLocationOnScreen();
int xOnScreen = x + scrollBarLocationOnScreen.x;
int yOnScreen = y + scrollBarLocationOnScreen.y;
return new MouseWheelEvent(
event.getComponent(), event.getID(), event.getWhen(),
event.getModifiersEx(),
x, y, xOnScreen, yOnScreen,
event.getClickCount(), event.isPopupTrigger(),
event.getScrollType(), event.getScrollAmount(),
event.getWheelRotation(),
event.getPreciseWheelRotation());
} else {
return event;
}
}
}
}