gpt4 book ai didi

java - 如何在 JPanel 更新时使 JScrollPane 滚动

转载 作者:行者123 更新时间:2023-12-02 03:48:38 25 4
gpt4 key购买 nike

我正在尝试实现一个 JPanel(添加到 JScrollPane 中)。这个想法是在 JPanel 上绘制一系列矩形。其中一个矩形具有不同的颜色。这个想法是,当应用程序运行时,我应该能够添加更多这些矩形(如果需要)或在当前绘制的矩形之间移动。我有左/右移动按钮,可以让我在矩形之间移动。现在的问题是,当我可以在按钮之间移动时,但 JPanel 更新时 JScrollPane 不会移动。如下图所示,假设我位于值为 [a] 的矩形中,其颜色为橙色。现在我可以向左或向右移动,但 JScrollPane 保持不变。如何让 JScrollPane 随矩形移动? The panel screenshot

我有一个执行所有绘图的文件 (TapeArea) 和一个将 3 个 TapeArea 实例捆绑在一起的文件 (TapePanel)。

import java.awt.Color;
import javax.swing.Timer;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowListener;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;


import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;

public class TapeArea extends JPanel {

private final Color BG_COLOR = new Color(200,200,200);
private final Color DEFAULT_CELL_COLOR = Color.white;
private final Color CURRENT_CELL_COLOR = Color.orange;
private final Color CELL_INDEX_COLOR = new Color(0, 130, 0);
private final int FONT_STYLE = Font.BOLD;
private final String FONT_NAME = "Monotype";
private final double INITIAL_OFFSET = -1.5;


int cellWidth = 40;
int cellHeight = 40;
int fontSize = 20;
boolean tapeInit = false;
int leftMostCell = 0, rightMostCell = 0;
double newLeftCellWidth = 0, newRightCellWidth = 0;
boolean newLeftCell = false, newRightCell = false;
Color currentTextColor = Color.black;
double offset = INITIAL_OFFSET;
int origin = 0;

Dimension areaSize;
int filler;
Tape tape;
FlowLayout layout;

int x = 10; //Start Drawing from X=10
int delay = 500; //milliseconds

public TapeArea(Tape t){
tape = t;
layout = new FlowLayout();
setLayout(layout);
setPreferredSize(new Dimension(1200,50));


// ActionListener counter = new ActionListener() {
// public void actionPerformed(ActionEvent evt)
// {
// stepOneTapeCell();
// repaint();
// x++;
// }};
// new Timer(delay, counter).start();
}




public void paintComponent(Graphics g){
int i,drawPos;
int yAlign;
int fontScalingFactor;
int stringWidth, stringHeight;
int index = 0, startAt, cellsToDraw, currentPosition;
int tapeLength;
String symbol;
FontRenderContext DEFAULT_FONT_RENDER_CONTEXT =
new FontRenderContext(null, false, false);
Rectangle2D charBounds;

Graphics2D g2d = (Graphics2D) g;
super.paintComponent(g2d);

if(tape == null)
return;


g2d.setColor(BG_COLOR);
g2d.fillRect(0,0,getWidth(), getHeight());

tapeLength = tape.getSize();

if(areaSize != null)
if(areaSize.width != getSize().width || areaSize.height != getSize().height)
tapeInit = false;

areaSize = getSize();
yAlign = areaSize.height / 2;

cellWidth = getHeight() - 2;
if(cellWidth > 40) {
cellWidth = 40;
}
cellHeight = cellWidth;
fontSize = cellWidth / 2;



if(newLeftCell) {
startAt = 1;
cellsToDraw = tapeLength - 1;
currentPosition = 0;
} else if(newRightCell) {
startAt = 0;
cellsToDraw = tapeLength - 1;
currentPosition = tapeLength - 2;
} else {
startAt = 0;
cellsToDraw = tapeLength;
currentPosition = tape.getCurrentPosition();
}
currentPosition = tape.getCurrentPosition();

//determine the number of cells to left and right on the tape
if(!tapeInit){
for(filler = 0; cellWidth * (1 + 2*filler) <= areaSize.width; filler++);
filler += 2;

leftMostCell = currentPosition - filler;
rightMostCell = leftMostCell + 2*filler;

while(-leftMostCell < rightMostCell - tapeLength - 1 && 0 < rightMostCell - tapeLength - 1) {
leftMostCell--;
rightMostCell--;
}
while(-leftMostCell > rightMostCell - tapeLength + 1 && leftMostCell < 0) {
leftMostCell++;
rightMostCell++;
}

}//end of if(!tapeInit)



if(origin != tape.getOrigin()){
leftMostCell++;
rightMostCell++;
}
origin = tape.getOrigin();
tapeInit = true;

//draw tape cells
for(drawPos = 0, i = leftMostCell; i <= rightMostCell; i++, drawPos++){

//what symbol to be drawn on the cell
if(i >= 0 && i < tapeLength)
symbol = (String) tape.getSymbolAt(i);
else
symbol = tape.getFillSymbol();

//indicate current tape cell by coloring it
if(i == currentPosition)
g2d.setColor(CURRENT_CELL_COLOR);
else
g2d.setColor(DEFAULT_CELL_COLOR);

g2d.fillRect((int)((newLeftCellWidth + drawPos + offset) * cellWidth), yAlign - cellHeight/2,
cellWidth, cellHeight);

g2d.setColor(Color.black);
g2d.drawRoundRect((int)((newLeftCellWidth + drawPos + offset) * cellWidth), yAlign - cellHeight/2,
cellWidth, cellHeight, 10, 10);

//draw symbols on cells
charBounds = g.getFont().getStringBounds(symbol,
DEFAULT_FONT_RENDER_CONTEXT);

stringWidth = (int)Math.ceil(charBounds.getWidth());
stringHeight = (int)Math.ceil(charBounds.getHeight());

//if symbol is multi-character, font may be adjusted so it will fit
fontScalingFactor = (int)Math.ceil((double)stringWidth/(double)cellWidth);
g.setFont(new Font(FONT_NAME, FONT_STYLE, fontSize/fontScalingFactor));

charBounds = g.getFont().getStringBounds(symbol,
DEFAULT_FONT_RENDER_CONTEXT);

stringWidth = (int)Math.ceil(charBounds.getWidth());
stringHeight = (int)Math.ceil(charBounds.getHeight());

if(i == tape.getCurrentPosition()) {
g.setColor(currentTextColor);
}

g.drawString(symbol,
(int)((newLeftCellWidth + drawPos + 0.5 + offset) * cellWidth - (stringWidth/2)),
(int)(yAlign + (stringHeight/4)));

g.setFont(new Font(FONT_NAME, Font.PLAIN, fontSize/(2 * fontScalingFactor)));
g.setColor(CELL_INDEX_COLOR);

g.drawString(Integer.toString(i - origin),
(int)((newLeftCellWidth + drawPos + 0.3 + offset) * cellWidth - (stringWidth/2)),
(int)(yAlign + 0.45 * cellHeight));
index++;

}//end of for() drawing tape cells



}

void setTapeData(String m, Tape p){
p.removeAllTapeData();
p.addDataToTape(m);
}


void stepOneTapeCell(String direction){
switch(direction){
case "L":
if(tape.getCurrentPosition() > tape.getOrigin()){
tape.setCurrentPosition(tape.getCurrentPosition() - 1);
revalidate();
repaint();
}
//tape.shiftLeft();
break;
case "R":
if(tape.getCurrentPosition() < tape.getSize()-1){
tape.setCurrentPosition(tape.getCurrentPosition() + 1);
revalidate();
repaint();
}
// tape.setCurrentPosition(tape.getCurrentPosition() + 1);
// repaint();
// tape.shiftRight();
// repaint();
break;
}
}


}//end of class TapePanel

TapePanel 文件:

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;

public class TapePanel extends JPanel implements MyJPanel{

private final int ROWS = 3;
private final int COLS = 1;
private final int TAPE_ORIGINAL_POSITION = 0;
private int NUM_TAPES = 3;
GridLayout layout;
Tape [] tapes;
TapeArea [] tapeArea;
JScrollPane sp1, sp2, sp3;

Border blackLine, border,margin;
TitledBorder title;

public TapePanel(Tape t1, Tape t2, Tape t3){

tapes = new Tape[NUM_TAPES];
tapes[0] = t1;
tapes[1] = t2;
tapes[2] = t3;
initiateComps();
addCompsToLayout();
}


public void initiateComps() {
// TODO Auto-generated method stub
layout = new GridLayout(ROWS,COLS);
setLayout(layout);

blackLine = BorderFactory.createLineBorder(Color.BLACK);
title = BorderFactory.createTitledBorder(blackLine,"Tapes");
title.setTitleJustification(TitledBorder.LEFT);
border = title.getBorder();
margin = new EmptyBorder(15,15,15,15);
title.setBorder(new CompoundBorder(margin,border));
setBorder(title);

tapeArea = new TapeArea[NUM_TAPES];
tapeArea[0] = new TapeArea(tapes[0]);
tapeArea[1] = new TapeArea(tapes[1]);
tapeArea[2] = new TapeArea(tapes[2]);

sp1 = new JScrollPane(tapeArea[0],JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
sp1.setPreferredSize(new Dimension(200,70));
sp2 = new JScrollPane(tapeArea[1],JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
sp2.setPreferredSize(new Dimension(200,70));
sp3 = new JScrollPane(tapeArea[2],JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
sp3.setPreferredSize(new Dimension(200,70));

//setBorder(new EmptyBorder(20,15,15,15));
}

@Override
protected void paintComponent(Graphics g) {
// TODO Auto-generated method stub
super.paintComponent(g);

}
void repaintTapeArea(){
for(int i = 0; i < NUM_TAPES;i++){
tapeArea[i].revalidate();
tapeArea[i].repaint();
}

}

void resetAllTapes(){

for(int i = 0; i < NUM_TAPES; i++){
tapeArea[i].setTapeData("", tapes[i]);
tapeArea[i].tape.setCurrentPosition(TAPE_ORIGINAL_POSITION);
}

}
void setTapeData(String m, Tape p, int tapeNumber){
tapeArea[tapeNumber].setTapeData(m, p);
}

void stepOneCell(int tapeNumber, String direction){
tapeArea[tapeNumber].stepOneTapeCell(direction);
}

@Override
public void addCompsToLayout() {
// TODO Auto-generated method stub
add(sp1);
add(sp2);
add(sp3);
}


@Override
public void addComponent(Component comp, int zone, int row, int col, int width, int height) {
// TODO Auto-generated method stub

}

public static void main(String [] args){

JFrame f = new JFrame();
f.add(new TapePanel(new Tape("a b c d"),new Tape("a b c d"),new Tape("a b")));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);

f.pack();

}
}

磁带只是一个简单的链表。

最佳答案

I only get 14 rectangles on the screen that I can move over with. If i add more than that, then they will not be visible.

仅当添加到滚动 Pane 的组件的首选大小大于滚动 Pane 的大小时,才会发生滚动。

您需要重写自定义绘画面板的 getPreferredSize() 方法,以反射(reflect)每个矩形覆盖的区域。

因此,当您向右或向下移动矩形时,您可能需要调整首选尺寸。

关于java - 如何在 JPanel 更新时使 JScrollPane 滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36081095/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com