Сначала прочитайте:
для получения дополнительной информации о том, как рисование работает в Swing.
Далее читайте:
чтобы лучше понять проблему параллелизма в Swing - короткой версии, Swing НЕ является потокобезопасным и является однопоточным.Это вызывает ряд проблем, когда вы хотите выполнить повторяющиеся действия, которые обновляют пользовательский интерфейс.
Затем перейдите к чтению Как использовать Swing Timers для возможного решения.
Давайте начнем выявлять основные проблемы ...
Это ...
contentPane = new JPanel();
contentPane.setLayout(null);
, как правило, плохая идея, но вы все равно ее не используете, так что это просто белый шум
Это ...
custRect = new CustomRectangle(getContentPane().getSize());
ошибочно, потому что в то время, когда вы запрашиваете размер его contentPane
, оно не было реализовано или расположение на экране, поэтому его результат равен 0x0
.Вы все равно не должны полагаться на это, и если вы хотите узнать размер контейнера, запросите его, когда он вам действительно нужен.
Далее ...
private Graphics2D g2d = null;
Вам следуетникогда не поддерживайте ссылку на любой графический контекст, который вы не создали.В Swing контекст разделяется между всеми нарисованными компонентами, что означает, что он может быть грязным, с другим содержимым или обрезанным, чтобы исключить область, которую вы хотите нарисовать.
И, наконец, ....
@Override
public void paintComponent(Graphics g) {
g2d = (Graphics2D) g;
Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minutes = calendar.get(Calendar.MINUTE);
int seconds = calendar.get(Calendar.SECOND);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Thread th = new Thread() {
public void run() {
while(true) {
for(int i = 0; i < nums.length; i++)
generalCall(nums[i]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};th.start();
}
?
paintComponent
будет вызываться всякий раз, когда Swing решит, что ваш компонент необходимо перекрасить, при первом понимании это может быть несколько раз подряд, то естьчисло запущенных Thread
с.
Paint должен выполнять одну работу, рисовать текущий контекст компонента, ничего больше.В вашем случае Swing Timer
был бы более жизнеспособным и безопасным решением.
И, если его почистить, он может выглядеть примерно так ...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;
public class MainWindow extends JFrame {
private CustomRectangle custRect = null;
private JButton btnCancel;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainWindow frame = new MainWindow();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public MainWindow() {
getContentPane().setBackground(Color.BLACK);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
custRect = new CustomRectangle();
getContentPane().add(custRect);
getContentPane().add(getBtnCancel(), BorderLayout.SOUTH);
}
private Color complementaryColor(Color background) {
int alpha = background.getAlpha();
int red = background.getRed();
int blue = background.getBlue();
int green = background.getGreen();
// find compliments
red = (~red) & 0xff;
blue = (~blue) & 0xff;
green = (~green) & 0xff;
return new Color(red, green, blue, alpha);
}
private JButton getBtnCancel() {
if (btnCancel == null) {
btnCancel = new JButton("Cancel");
btnCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
btnCancel.setBackground(null);
btnCancel.setBorder(null);
btnCancel.setForeground(complementaryColor(getContentPane().getBackground()));
btnCancel.setFocusPainted(false);
}
return btnCancel;
}
private class CustomRectangle extends JComponent {
private byte[] nums = new byte[]{0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B};
public CustomRectangle() {
Timer timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
}
public byte[] getNums() {
return nums;
}
@Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (int i = 0; i < nums.length; i++) {
generalCall(g2d, nums[i]);
}
}
public void generalCall(Graphics2D g2d, byte val) {
drawAHoursHigh(g2d, val);
drawBHoursHigh(g2d, val);
drawCHoursHigh(g2d, val);
drawDHoursHigh(g2d, val);
drawEHoursHigh(g2d, val);
drawFHoursHigh(g2d, val);
drawGHoursHigh(g2d, val);
}
private Color getColor(byte val, int shift) {
int r = 255;
int g = 0;
int b = 0;
int a = 255 * (val >> shift) & 1;
System.out.println("R: " + r + " G: " + g + " B: " + b + " Alpha: " + a);
if (a == 0) {
return new Color(15, 15, 15);
} else {
return new Color(r, g, b);
}
}
private void drawAHoursHigh(Graphics2D g2d, byte val) {
System.out.print("A: ");
Shape a = new RoundRectangle2D.Double(60, 20, 78, 18, 10, 10);
g2d.setColor(getColor(val, 6));
g2d.fill(a);
g2d.draw(a);
}
private void drawBHoursHigh(Graphics2D g2d, byte val) {
System.out.print("B: ");
Shape b = new RoundRectangle2D.Double(140, 40, 18, 98, 10, 10);
g2d.setColor(getColor(val, 5));
g2d.fill(b);
g2d.draw(b);
}
private void drawCHoursHigh(Graphics2D g2d, byte val) {
System.out.print("C: ");
Shape c = new RoundRectangle2D.Double(140, 160, 18, 98, 10, 10);
g2d.setColor(getColor(val, 4));
g2d.fill(c);
g2d.draw(c);
}
private void drawDHoursHigh(Graphics2D g2d, byte val) {
System.out.print("D: ");
Shape d = new RoundRectangle2D.Double(60, 260, 78, 18, 10, 10);
g2d.setColor(getColor(val, 3));
g2d.fill(d);
g2d.draw(d);
}
private void drawEHoursHigh(Graphics2D g2d, byte val) {
System.out.print("E: ");
Shape e = new RoundRectangle2D.Double(40, 160, 18, 98, 10, 10);
g2d.setColor(getColor(val, 2));
g2d.fill(e);
g2d.draw(e);
}
private void drawFHoursHigh(Graphics2D g2d, byte val) {
System.out.print("F: ");
Shape f = new RoundRectangle2D.Double(40, 40, 18, 98, 10, 10);
g2d.setColor(getColor(val, 1));
g2d.fill(f);
g2d.draw(f);
}
private void drawGHoursHigh(Graphics2D g2d, byte val) {
System.out.print("G: ");
Shape g = new RoundRectangle2D.Double(60, 140, 78, 18, 10, 10);
g2d.setColor(getColor(val, 0));
g2d.fill(g);
g2d.draw(g);
}
}
}