У меня есть простое Java-приложение Swing, которое выполняет поиск, и результаты отображаются на новой вкладке. Пока идет поиск, я хочу показать значок прогресса или анимацию в заголовке вкладки. Я попытался добавить значок gif, но он не анимируется. Есть ли причина, по которой это не работает?
JTabbedPane: показать ход выполнения задачи на вкладке
Ответы (3)
руководство Swing по индикаторам выполнения (и общее отображение прогресса ) это очень хорошее место для начала. В нем показано, как выполнять длительные операции в рабочем потоке с помощью SwingWorker
и обновления пользовательского интерфейса через определенные промежутки времени, чтобы показать пользователю ход выполнения длительной операции. Существует еще одно руководство для получения дополнительной информации о SwingWorker
и параллелизме в Swing.
И, как всегда, этот сайт наполнен примерами. Например, мой предыдущий ответ использует класс SwingWorker
, чтобы показать прогресс до Пользователь
Изменить
Поскольку я пропустил часть названия вкладки в вашем вопросе. Вы можете создать «значок прогресса» и установить его на вкладке. Затем SwingWorker
можно использовать для обновления значка.
Примером такого значка является , который в основном представляет собой изображение, которое вы поворачиваете каждый раз, когда достигается некоторый прогресс. . В руководстве по вкладкам показано, как добавлять значки в вкладки (или даже использовать пользовательские компоненты)
Изменить2
Поскольку кажется, что мой Mac в сочетании с JDK1.7 значительно упрощает отображение анимированного gif, чем на других системах, я также создал небольшой SSCCE, очень похожий на тот, что у Эндрю, но с вращающимся значком, который не похож на него. был создан, цитирую, «сумасшедшим шимпанзе». Код вращающегося значка взят с этого сайта (я использовал урезанный вниз и добавил таймер). Единственное, чем я не очень доволен, это тот факт, что мне нужно передать панель с вкладками вращающемуся значку для запуска. Возможное решение — вытащить таймер за пределы класса RotatingIcon
, но это всего лишь SSCCE. Изображения не включены, но были найдены с помощью Google.
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;
import javax.swing.Timer;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
public class ProgressTabbedPane {
public static void main( String[] args ) {
EventQueue.invokeLater( new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame( "RotatingIcon" );
JTabbedPane tabbedPane = new JTabbedPane( );
tabbedPane.addTab( "Searching", new RotatingIcon( new ImageIcon( "resources/images/progress-indeterminate.png" ), tabbedPane ),
new JLabel( new ImageIcon( "resources/images/rotatingIcon.gif" ) ) );
frame.getContentPane().add( tabbedPane );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.pack();
frame.setVisible( true );
}
} );
}
private static class RotatingIcon implements Icon{
private final Icon delegateIcon;
private double angleInDegrees = 90;
private final Timer rotatingTimer;
private RotatingIcon( Icon icon, final JComponent component ) {
delegateIcon = icon;
rotatingTimer = new Timer( 100, new ActionListener() {
@Override
public void actionPerformed( ActionEvent e ) {
angleInDegrees = angleInDegrees + 10;
if ( angleInDegrees == 360 ){
angleInDegrees = 0;
}
component.repaint();
}
} );
rotatingTimer.setRepeats( false );
rotatingTimer.start();
}
@Override
public void paintIcon( Component c, Graphics g, int x, int y ) {
rotatingTimer.stop();
Graphics2D g2 = (Graphics2D )g.create();
int cWidth = delegateIcon.getIconWidth() / 2;
int cHeight = delegateIcon.getIconHeight() / 2;
Rectangle r = new Rectangle(x, y, delegateIcon.getIconWidth(), delegateIcon.getIconHeight());
g2.setClip(r);
AffineTransform original = g2.getTransform();
AffineTransform at = new AffineTransform();
at.concatenate(original);
at.rotate(Math.toRadians( angleInDegrees ), x + cWidth, y + cHeight);
g2.setTransform(at);
delegateIcon.paintIcon(c, g2, x, y);
g2.setTransform(original);
rotatingTimer.start();
}
@Override
public int getIconWidth() {
return delegateIcon.getIconWidth();
}
@Override
public int getIconHeight() {
return delegateIcon.getIconHeight();
}
}
}
Скриншот для справки. Жаль, что значки на скриншоте не вращаются.
Clip
. В то время я разрабатывал Ubuntu, и реализация JRE позволяла использовать клипы произвольного размера (по крайней мере, до OutOfMemoryError
). Но в Sun JRE для Windows 1 секунда звука CD-качества была всем, что можно было загрузить. :( Кстати - только что проверил эту анимацию изображения на Win 7 с использованием Java 1.6.0_29.
- person Andrew Thompson; 07.04.2012
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
public class ImageOnTab {
ImageOnTab() {
final BufferedImage image = new BufferedImage(
32,32,BufferedImage.TYPE_INT_RGB);
final JTabbedPane pane = new JTabbedPane();
ImageIcon icon = new ImageIcon(image);
pane.addTab( "Progress", icon, new JTree() );
ActionListener listener = new ActionListener() {
int x = 0;
int step = 1;
public void actionPerformed(ActionEvent ae) {
Graphics g = image.createGraphics();
x+=step;
if (step>0) {
if (x>32) {
step=-step;
}
} else if (x<0) {
step=-step;
}
g.setColor(Color.ORANGE);
g.fillRect(0,0,32,32);
g.setColor(Color.RED);
g.fillRect(0,0,x,32);
g.dispose();
pane.repaint();
}
};
Timer timer = new Timer(100,listener);
timer.start();
JOptionPane.showMessageDialog(null, pane);
}
public static void main(String[] args) throws Exception {
//Create the GUI on the event dispatching thread
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
new ImageOnTab();
}
});
}
}
@Эндрю Томпсон
It would be great if the J2SE supported animated GIFs 'out of the box'
in more situations. I tried that animated GIF (nice image, BTW) as a
tab icon, and no, it remains static.
Я не хочу читать целиком ...., но соберу код вашим и @trashgod's majesty
1) используйте Htlm
(я плохо разбираюсь в простом Html)
2) используйте GlassPane
с JLabel#(setOpaque(true))
3) используйте JLayer
(JXLayer
лучше, потому что Sn'Oracle удаляет важные методы == мое мнение)
4) вам нужно форсировать ..... для Swing JComponents от @aterai
5) Анимированная иконка Роба несколько раз упомянула о поддержке со стороны Роба для JTabbedPane
код
import java.awt.*;
import java.awt.event.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
//https://stackoverflow.com/questions/3483485/java-jprogressbar-or-equivalent-in-a-jtabbedpane-tab-title/3484251#3484251
public class JTabbedTest {
private JFrame f = new JFrame();
private JTabbedPane jtp = new JTabbedPane();
private URL url = null;
public JTabbedTest() {
try {
url = new URL("http://pscode.org/media/starzoom-thumb.gif");
} catch (MalformedURLException ex) {
Logger.getLogger(JTabbedTest.class.getName()).log(Level.SEVERE, null, ex);
}
ImageIcon ii = new ImageIcon(url);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jtp.setPreferredSize(new Dimension(400, 200));
createTab("Reds", Color.RED);
createTab("Greens", Color.GREEN);
createTab("Blues", Color.BLUE);
f.add(jtp, BorderLayout.CENTER);
jtp.setTitleAt(2, "<html><img src=" + ii + " width=20 height=20></img></html>");
// change foreground Color for disabled tab
/*jtp.setTitleAt(2, "<html><font color=" + (jtp.isEnabledAt(2) ? "black" : "red") + ">"
+ jtp.getTitleAt(2) + "</font></html>");*/
Rectangle tabBounds = jtp.getBoundsAt(0);
Container glassPane = (Container) f.getRootPane().getGlassPane();
glassPane.setVisible(true);
glassPane.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.fill = GridBagConstraints.NONE;
gbc.insets = new Insets(tabBounds.y + 23, 0, 0, 5);
gbc.anchor = GridBagConstraints.NORTHEAST;
JButton button = new JButton("My Button Position", ii);
button.setPreferredSize(new Dimension(button.getPreferredSize().width, (int) tabBounds.getHeight() - 2));
glassPane.add(button, gbc);
f.pack();
f.setVisible(true);
}
private void createTab(String name, Color color) {
ProgressIcon icon = new ProgressIcon(color);
jtp.addTab(name, icon, new ColorPanel(jtp, icon));
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JTabbedTest jTabbedTest = new JTabbedTest();
}
});
}
private static class ColorPanel extends JPanel implements ActionListener {
private static final Random rnd = new Random();
private static final long serialVersionUID = 1L;
private final Timer timer = new Timer(1000, this);
private final JLabel label = new JLabel("Stackoverflow!");
private final JTabbedPane parent;
private final ProgressIcon icon;
private final int mask;
private int count;
public ColorPanel(JTabbedPane parent, ProgressIcon icon) {
super(true);
this.parent = parent;
this.icon = icon;
this.mask = icon.color.getRGB();
this.setBackground(icon.color);
label.setForeground(icon.color);
this.add(label);
timer.start();
}
@Override
public void actionPerformed(ActionEvent e) {
this.setBackground(new Color(rnd.nextInt() & mask));
this.icon.update(count += rnd.nextInt(8));
this.parent.repaint();
}
}
private static class ProgressIcon implements Icon {
private static final int H = 16;
private static final int W = 3 * H;
private Color color;
private int w;
public ProgressIcon(Color color) {
this.color = color;
}
public void update(int i) {
w = i % W;
}
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
g.setColor(color);
g.fillRect(x, y, w, H);
}
@Override
public int getIconWidth() {
return W;
}
@Override
public int getIconHeight() {
return H;
}
}
}
JProgressBar
среди компонентов интересующей вкладки, либо общим индикатором выполнения (за пределами области с вкладками), который показывает ход выполнения любой выбранной вкладки. Есть предложения? tnx 1) Не делайте этого. 2) Правильно произносите такие слова, как «спасибо», или, что еще лучше, пропускайте их — это шум. - person Andrew Thompson   schedule 07.04.2012