我试图动画的选择和插入排序算法的过程,矩形显示排序值的高度。
当选择/插入排序算法中发生单个更改时,我调用repaint(),但它似乎没有完全重新绘制它们,只是部分矩形发生了更改。在最终结果中,它实际上根本不显示完全排序的数组。
这两种算法都经过测试和工作,因此问题似乎与动画他们的过程。
有什么帮助吗?
MyPaint.java
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);
}
}SortDriver.java
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;
}
}发布于 2017-01-13 16:56:18
首先,您不应该重写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
}
}其次,避免使用空布局。最好在您的情况下为BorderLayout使用类似JFrame的东西。
此外,您还必须了解事件调度线程。对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对象作为监视器。
https://stackoverflow.com/questions/41636669
复制相似问题