#java #swing #timer #long-integer #jprogressbar
#java — язык #качать #таймер #длинное целое число #jprogressbar #java
Вопрос:
Как я могу сделать так, чтобы индикатор выполнения медленно снижался с течением времени?
class GamePanel extends JPanel implements MouseListener, ActionListener
{
private JButton quit;
private JButton q;
private Font loadFont;
public GamePanel()
{
setBackground(Color.blue); // sets background color
this.setLayout(null);
quit = new JButton("Quit");
quit.addActionListener(this);
quit.setBounds(550, 700, 100, 30);
this.add(quit);
q = new JButton("Questions");
q.addActionListener(this);
q.setBounds(100, 100, 120, 30);
this.add(q);
loadFont = new Font("Serif", Font.PLAIN, 30);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.black);
g.fillRect(80, 100, 610, 560);
g.setColor(Color.white);
g.fillRect(90, 110, 110, 100);// 1st column
g.fillRect(90, 220, 110, 100);//
g.fillRect(90, 330, 110, 100);//
g.fillRect(90, 440, 110, 100);//
g.fillRect(90, 550, 110, 100);//
g.fillRect(210, 110, 110, 100);// 2nd column
g.fillRect(210, 220, 110, 100);//
g.fillRect(210, 330, 110, 100);//
g.fillRect(210, 440, 110, 100);//
g.fillRect(210, 550, 110, 100);//
g.fillRect(330, 110, 110, 100);// 3rd column
g.fillRect(330, 220, 110, 100);//
g.fillRect(330, 330, 110, 100);//
g.fillRect(330, 440, 110, 100);//
g.fillRect(330, 550, 110, 100);//
g.fillRect(450, 110, 110, 100);// 4th column
g.fillRect(450, 220, 110, 100);//
g.fillRect(450, 330, 110, 100);//
g.fillRect(450, 440, 110, 100);//
g.fillRect(450, 550, 110, 100);//
g.fillRect(570, 110, 110, 100);// 5th column
g.fillRect(570, 220, 110, 100);//
g.fillRect(570, 330, 110, 100);//
g.fillRect(570, 440, 110, 100);//
g.fillRect(570, 550, 110, 100);//
g.setColor(Color.green);
g.setFont(loadFont);
g.drawString(input ":", 100, 710);
}
public void actionPerformed(ActionEvent e)
{
String order = e.getActionCommand();
if(order.equals("Quit"))
cards.show(c, "Introduction");
if(order.equals("Questions"))
cards.show(c, "Questions");
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
class QuestionPanel extends JPanel implements ActionListener
{
private long startTime, elapsedTime;
private Timer timer;
private int countdown;
private Font loadFont;
public QuestionPanel()
{
setBackground(Color.pink); // sets background color
this.setLayout(null); // moved into constructor from ActionPerformed: only change layout in constructor
startTime = 0;
elapsedTime = 0;
countdown = 590;
loadFont = new Font("Segoe Script", Font.BOLD, 20);
if(timer == null)
{// use the biggest value possible that provides your desired time keeping precision (usually no less than 15 on Windows)
timer = new Timer(100, this);
startTime = System.currentTimeMillis(); // gets start time in milliseconds
timer.start();
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.fillRect(100, 100, 600, 25);
g.setColor(Color.green);
g.fillRect(105, 105, countdown, 15);
g.setColor(Color.black);
g.setFont(loadFont);
g.drawString("" ((System.currentTimeMillis() - startTime) / 1000.0), 100, 80); // display remaining time
}
public void actionPerformed(ActionEvent e)
{
String command = e.getActionCommand();
elapsedTime = System.currentTimeMillis() - startTime;
if(elapsedTime < (5000))
{
countdown--;
repaint();
}
else
{
timer.stop();
if(timer == null)
{
timer = new Timer(500, this);
timer.start();
}
}
if(elapsedTime >= (5000)) // can't use == here because of limited precision of system clock
cards.show(c, "Correct!");
}
}
class AnswerPanel extends JPanel implements ActionListener
{
private JButton revert;
public AnswerPanel()
{
setBackground(Color.yellow); // sets background color
this.setLayout(null);
revert = new JButton("Back");
revert.addActionListener(this);
revert.setBounds(340, 700, 100, 30);
this.add(revert);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
}
public void actionPerformed(ActionEvent e)
{
String directive = e.getActionCommand();
if(directive.equals("Back"))
cards.show(c, "Start");
}
}
class FailPanel extends JPanel implements ActionListener
{
private JButton turnaround;
public FailPanel()
{
setBackground(Color.green); // sets background color
this.setLayout(null);
turnaround = new JButton("Back");
turnaround.addActionListener(this);
turnaround.setBounds(340, 700, 100, 30);
this.add(turnaround);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
}
public void actionPerformed(ActionEvent e)
{
String bidding = e.getActionCommand();
if(bidding.equals("Back"))
cards.show(c, "Start");
}
}
}// end of the entire program
Комментарии:
1. Я бы хотел, чтобы люди взглянули на панель вопросов. Я пытаюсь запустить обратный отсчет таймера, пока индикатор выполнения также снижается. Когда таймер достигает 0 (после запуска с 5), предполагается, что будет показана другая панель. Другая проблема заключается в том, что таймер запускается еще до того, как я доберусь до этой панели; Я хочу иметь возможность контролировать, когда запускается таймер.
2. Святая стена текста, Бэтмен! Я бы попробовал свести проблему к настолько небольшому примеру, насколько вы можете это сделать.
3. Я решительно поддерживаю предложение СКРМ. Это просто слишком много кода. Вам придется приложить некоторые усилия, чтобы сделать его одновременно меньшим и понятным, но это потраченные не зря усилия. В противном случае у многих найдутся дела поважнее, чем проводить воскресные вечера за чтением трехтомника по программному обеспечению.
4. @thynoob: У меня есть 5 писем для тебя SSCCE . Подготовьте SSCCE, и, скорее всего, проблема (а также решение) станут понятны по мере того, как вы это сделаете. Если этого не произойдет, по крайней мере, у вас будет короткий фрагмент кода, который другие люди, вероятно, рассмотрят более внимательно. Как бы то ни было, вы просите нас просмотреть почти 450 строк кода в поисках ошибки. Ваш запрос, скорее всего, будет проигнорирован. @HFOE спасибо за форматирование кода.
5. Ваша программа также выиграет от того, что вы сделаете это, поскольку это может помочь вам в достижении вашей цели отделить программную логику от кода GUI. Кроме того, вам захочется избавиться от всего этого абсолютного позиционирования и определения размеров и вместо этого использовать менеджеры компоновки, особенно если вы хотите, чтобы пользователи с мониторами разного размера и разрешением экрана могли видеть ваш графический интерфейс. Я не могу видеть это полностью на моем, например.
Ответ №1:
Извините, я все еще не мог найти мотивации на самом деле прочитать ваш код, но просто собрал этот пример на основе вопроса. Посмотрим, подскажет ли это вам какие-нибудь идеи.
Обратите внимание, что это SSCCE и использует всего 40 строк кода.
import java.awt.event.*;
import javax.swing.*;
class CountDownProgressBar {
Timer timer;
JProgressBar progressBar;
CountDownProgressBar() {
progressBar = new JProgressBar(JProgressBar.VERTICAL, 0, 10);
progressBar.setValue(10);
ActionListener listener = new ActionListener() {
int counter = 10;
public void actionPerformed(ActionEvent ae) {
counter--;
progressBar.setValue(counter);
if (counter<1) {
JOptionPane.showMessageDialog(null, "Kaboom!");
timer.stop();
}
}
};
timer = new Timer(1000, listener);
timer.start();
JOptionPane.showMessageDialog(null, progressBar);
}
public static void main(String[] args) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
CountDownProgressBar cdpb = new CountDownProgressBar();
}
});
}
}
Комментарии:
1. @thynoob: Код Эндрюса не просто короткий, он также компилируемый, исполняемый и тестируемый. Поскольку это кратко, мы можем быстро разобраться. Поскольку он компилируется и выполняется, мы все можем запускать этот код без изменений, изменять его, улучшать и исправлять любые ошибки в нем за короткий промежуток времени.
Ответ №2:
Судя по всему, весь этот код находится в большом файле Java? Это плохая идея.
У вас должна быть веская причина для определения класса как внутреннего класса, и, судя по всему, у вас ее нет для QuestionPanel и других.
Что касается проблемы, ваш paintComponent
метод вызывается каждый раз, когда обновляется ваш счетчик, что сейчас происходит примерно раз в 0,1 секунды, но вы отмечаете только на 1 пиксель при каждом обновлении, так что к концу 5 секунд вы отсекаете 10 * 5 пикселей (50). Что вам следует сделать, так это обновить индикатор выполнения с помощью другого механизма, такого как вычисление текущего времени обработки:
long processed = System.currentTimeMillis() - startTime;
double percent = Math.max(0, 1 - processed / 5000.0);
int width = (int)(590 * percent);
Комментарии:
1. Почему бы просто не использовать JProgressBar?
2. Я предполагаю, что это для задания, но в остальном я согласен с вами.
3. я ценю ваш выбор входных данных, но есть ли способ сделать так, чтобы время восстановления отображалось с 5 секунд?
4. Да, измените последнюю строку, в которой отображается оставшееся время.
double remaining = 5 * percent; g.drawString(String.format("%.2f", remaining), 100, 80);
5. итак, я заменяю последнюю строку, которую вы только что дали, на последнюю строку кода, который вы дали мне первым? и затем, после этого, я поместил это в свой код, используя свои переменные, и все должно быть в порядке? o__o
Ответ №3:
Это определенно слишком много информации и очень широкий вопрос. Я бы сказал, что в лучшем случае вам нужно только включить код для класса, в котором находится таймер, и класса, в котором отображается индикатор выполнения.
Просматривая код, я предполагаю, что вы используете прямоугольник для рисования индикатора выполнения. Исходя из этого, одним из способов, которым вы могли бы это сделать, было бы использование переменной для хранения ширины полосы, и каждый раз, когда таймер тикает, уменьшайте ширину полосы на заданную величину. Затем просто установите ширину нарисованного прямоугольника на значение, сохраненное в переменной.