[英]Animation of java.awt rectangles not acting as wanted
我正在嘗試使用按高度顯示排序值的矩形為選擇和插入排序算法的過程設置動畫。
當我的選擇/插入排序算法中發生單個更改時,我調用repaint()
,但它似乎並沒有完全重新繪制它們,只有一些矩形發生了變化。 最終,它實際上根本沒有顯示完全排序的數組。
這兩種算法都經過了測試和工作,所以問題似乎在於它們的過程動畫。
有什么幫助嗎?
我的畫圖
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Timer;
import java.util.TimerTask;
public class MyPanel extends JPanel{
private static int[] mainArr;
private boolean reset = false;
private Timer t = new Timer();
private int[] tempArr;
public MyPanel(){
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(400, 400));
panel.setBackground(Color.WHITE);
panel.setLayout(new FlowLayout(FlowLayout.CENTER));
//JButton selButton = new JButton("Select Sort");
//panel.add(selButton);
add(panel);
}
public static void main(String[] args) {
SortDriver frame = new SortDriver();
mainArr = frame.getArr();
frame.setVisible(true);
}
}
排序驅動程序
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Graphics;
public class SortDriver extends JFrame implements ActionListener {
private int modeName;
private JButton startButton;
private JButton selButton;
private JButton insButton;
private JPanel mainPanel;
private MyPanel panel;
private int[] sortArr = new int[41];
public SortDriver() {
setLayout(null);
setPreferredSize(new Dimension(420, 420));
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new JPanel();
mainPanel.setBackground(Color.WHITE);
mainPanel.setBounds(0, 0, 420, 420);
mainPanel.setPreferredSize(new Dimension(400, 400));
//mainPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
add(mainPanel);
//Buttons
startButton = new JButton("Start");
startButton.addActionListener(this);
mainPanel.add(startButton);
selButton = new JButton("Select Sort");
selButton.addActionListener(this);
mainPanel.add(selButton);
insButton = new JButton("Insert Sort");
insButton.addActionListener(this);
mainPanel.add(insButton);
//Panel
panel = new MyPanel();
mainPanel.add(panel);
//Array
for(int i = 0; i <= 40; i++){
sortArr[i] = 0;
}
for(int i = 0; i <= 40; i++){
int random = (int)(Math.random() * 50 + 1);
sortArr[i] = random;
}
//Final
pack();
}
public void paint(Graphics g) {
for(int i = 0; i <= 40; i++){
g.fillRect(i * 10, 100, 5, sortArr[i]);
}
}
public void selectionSort (int[] list){
int min;
int temp;
for (int index = 0; index < list.length-1; index++){
min = index;
for (int scan = index+1; scan < list.length; scan++)
if (list[scan] - (list[min]) < 0) min = scan;
// Swap the values
temp = list[min];
list[min] = list[index];
list[index] = temp;
repaint();
}
//for(int i = 0; i <= list.length; i++){
// System.out.println(list[i]);
//}
}
public void insertionSort (int[] list){
for (int index = 1; index < list.length; index++){
int key = list[index];
int position = index;
// Shift larger values to the right
while (position > 0 && key - (list[position-1]) < 0){
list[position] = list[position-1];
position--;
repaint();
}
list[position] = key;
}
}
public void actionPerformed(ActionEvent event) {
if (event.getSource() == selButton) {
modeName = 1;
}
else if (event.getSource() == insButton) {
modeName = 2;
}
else if (event.getSource() == startButton) {
if(modeName == 1){
selectionSort(sortArr);
}
if(modeName == 2){
insertionSort(sortArr);
}
}
}
public int getMode(){
return modeName;
}
public int[] getArr(){
return sortArr;
}
}
首先,您不應覆蓋JFrame
的 paint 方法。 而重寫paintComponent()
一個的JPanel
用於定制圖。 您可以為此目的使用MyPanel
:
public class MyPanel extends JPanel{
public MyPanel(){
setBackground(Color.WHITE);
}
public synchronized void paintComponent(Graphics g) {
super.paintComponent(g);
// your paint code
}
}
其次,避免使用空布局。 最好在JFrame
的情況下使用BorderLayout 之類的東西。
此外,您必須了解Event Dispatch Thread 。 對 GUI 元素的操作必須在此線程上進行。
您應該在 EDT 上設置您的 GUI。 你可以在你的主方法中使用SwingUtilities.invokeLater()
來做到這一點:
SwingUtilities.invokeLater(() -> {
SortDriver frame = new SortDriver();
mainArr = frame.getArr();
frame.setVisible(true);
});
您應該考慮在單獨的線程中處理動畫,以便在 EDT 之外進行排序。 這是一個關於它原則上如何工作的小演示,以您的選擇排序為特色:
new Thread(() -> {
int min;
int temp;
final int delayMillis = 100;
long startTickTime = System.nanoTime();
for (int index = 0; index < list.length-1; index++){
synchronized(myPanel){
min = index;
for (int scan = index+1; scan < list.length; scan++)
if (list[scan] - (list[min]) < 0) min = scan;
// Swap the values
temp = list[min];
list[min] = list[index];
list[index] = temp;
}
myPanel.repaint();
try {
TimeUnit.NANOSECONDS.sleep(delayMillis*1000000-System.nanoTime()+startTickTime);
startTickTime = System.nanoTime();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
如您所見,我將更新選擇排序的代碼放入synchronized
塊中,以便與paintComponent()
方法同步。 這是必要的,因為繪制發生在 EDT 上,而排序發生在與 EDT 不同的線程上。 在示例中,我使用MyPanel
對象作為監視器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.