向JTable添加加载循环

发布于 2025-01-05 09:27:01 字数 299 浏览 4 评论 0原文

我有一个从数据库加载数据的 JTable。因为有时数据太多,我想在Jtable内添加一个加载圆圈来通知用户数据正在加载。这是我希望的图像:

在此处输入图像描述

这可能吗?在 Swing 中如何实现呢?

PS:我不想使用进度条,我只想要表格内的圆圈。

更新: 该表是 GUI 的一部分,我只想禁用或显示 JTable 内的加载,并保持其他组件不变。

I have a JTable that loads data from a database. Because sometimes there's too much data, I would like to add a loading circle inside the Jtable to notify the user that the data is being loaded. Here is an image of how I would like it to be:

enter image description here

Is this possible? How can it be done in Swing?

PS: I don't want to use the progress bar, I just want the circle inside the table.

UPDATE: The table is part of the GUI and I only want to disable or show the loading inside the JTable and leave the other components intact.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

猥琐帝 2025-01-12 09:27:02

这是 JLayer(Java 1.7.0) 版本,基于 How to Decorate Components with JLayer 类(Java 教程 > 使用 JFC/Swing 创建 GUI > 使用其他 Swing 功能)

import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import javax.swing.*;
import javax.swing.plaf.LayerUI;
import javax.swing.table.*;

public class TableWaitLayerTest {
  private final String[] columnNames = {"String", "Integer", "Boolean"};
  private final Object[][] data = {
    {"aaa", 12, true}, {"bbb", 5, false}, {"ccc", 9, false},
  };
  private final DefaultTableModel model = new DefaultTableModel(data, columnNames) {
    @Override public Class<?> getColumnClass(int column) {
      return getValueAt(0, column).getClass();
    }
  };
  private final JTable table = new JTable(model);
  private final JButton startButton = new JButton();
  private final WaitLayerUI layerUI = new WaitLayerUI();
  public JComponent makeUI() {
    startButton.setAction(new AbstractAction("start") {
      @Override public void actionPerformed(ActionEvent e) {
        layerUI.start();
        startButton.setEnabled(false);
        SwingWorker<String, Object[]> worker = new SwingWorker<String, Object[]>() {
          @Override public String doInBackground() {
            int current = 0, lengthOfTask = 120;
            while(current<lengthOfTask && !isCancelled()) {
              try {
                Thread.sleep(50);
              } catch(InterruptedException ie) {
                return "Interrupted";
              }
              publish(new Object[] {"aaa", current++, false});
            }
            return "Done";
          }
          @Override protected void process(java.util.List<Object[]> chunks) {
            for(Object[] array: chunks) {
              model.addRow(array);
            }
            table.scrollRectToVisible(
                table.getCellRect(model.getRowCount()-1, 0, true));
          }
          @Override public void done() {
            layerUI.stop();
            startButton.setEnabled(true);
            String text = null;
            if(isCancelled()) {
              text = "Cancelled";
            } else {
              try {
                text = get();
              } catch(Exception ex) {
                ex.printStackTrace();
                text = "Exception";
              }
            }
          }
        };
        worker.execute();
      }
    });
    JPanel p = new JPanel(new BorderLayout());
    p.add(new JButton("dummy"), BorderLayout.NORTH);
    p.add(new JLayer<JComponent>(new JScrollPane(table), layerUI));
    p.add(startButton, BorderLayout.SOUTH);
    return p;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new TableWaitLayerTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

//http://docs.oracle.com/javase/tutorial/uiswing/misc/jlayer.html
//How to Decorate Components with the JLayer Class
//(The Java? Tutorials > Creating a GUI With JFC/Swing > Using Other Swing Features)
//TapTapTap.java
class WaitLayerUI extends LayerUI<JComponent> implements ActionListener {
  private boolean mIsRunning;
  private boolean mIsFadingOut;
  private Timer mTimer;

  private int mAngle;
  private int mFadeCount;
  private int mFadeLimit = 15;

  @Override public void paint (Graphics g, JComponent c) {
    int w = c.getWidth();
    int h = c.getHeight();

    // Paint the view.
    super.paint (g, c);

    if (!mIsRunning) {
      return;
    }

    Graphics2D g2 = (Graphics2D)g.create();

    float fade = (float)mFadeCount / (float)mFadeLimit;
    // Gray it out.
    Composite urComposite = g2.getComposite();
    g2.setComposite(AlphaComposite.getInstance(
                      AlphaComposite.SRC_OVER, .5f * fade));
    g2.fillRect(0, 0, w, h);
    g2.setComposite(urComposite);

    // Paint the wait indicator.
    int s = Math.min(w, h) / 5;
    int cx = w / 2;
    int cy = h / 2;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setStroke(
      new BasicStroke(s / 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
    g2.setPaint(Color.white);
    g2.rotate(Math.PI * mAngle / 180, cx, cy);
    for (int i = 0; i < 12; i++) {
      float scale = (11.0f - (float)i) / 11.0f;
      g2.drawLine(cx + s, cy, cx + s * 2, cy);
      g2.rotate(-Math.PI / 6, cx, cy);
      g2.setComposite(AlphaComposite.getInstance(
                        AlphaComposite.SRC_OVER, scale * fade));
    }

    g2.dispose();
  }

  @Override public void actionPerformed(ActionEvent e) {
    if (mIsRunning) {
      firePropertyChange("tick", 0, 1);
      mAngle += 3;
      if (mAngle >= 360) {
        mAngle = 0;
      }
      if (mIsFadingOut) {
        if (--mFadeCount == 0) {
          mIsRunning = false;
          mTimer.stop();
        }
      } else if (mFadeCount < mFadeLimit) {
        mFadeCount++;
      }
    }
  }

  public void start() {
    if (mIsRunning) {
      return;
    }
    // Run a thread for animation.
    mIsRunning = true;
    mIsFadingOut = false;
    mFadeCount = 0;
    int fps = 24;
    int tick = 1000 / fps;
    mTimer = new Timer(tick, this);
    mTimer.start();
  }

  public void stop() {
    mIsFadingOut = true;
  }

  @Override public void applyPropertyChange(PropertyChangeEvent pce, JLayer l) {
    if ("tick".equals(pce.getPropertyName())) {
      l.repaint();
    }
  }

  @Override public void installUI(JComponent c) {
    super.installUI(c);
    ((JLayer)c).setLayerEventMask(
      AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK |
      AWTEvent.MOUSE_WHEEL_EVENT_MASK | AWTEvent.KEY_EVENT_MASK |
      AWTEvent.FOCUS_EVENT_MASK | AWTEvent.COMPONENT_EVENT_MASK);
  }
  @Override public void uninstallUI(JComponent c) {
    ((JLayer)c).setLayerEventMask(0);
    super.uninstallUI(c);
  }
  @Override public void eventDispatched(AWTEvent e, JLayer<? extends JComponent> l) {
    if(mIsRunning && e instanceof InputEvent) {
      ((InputEvent)e).consume();
    }
  }
}

Here's JLayer(Java 1.7.0) version, based on How to Decorate Components with the JLayer Class (The Java Tutorials > Creating a GUI With JFC/Swing > Using Other Swing Features)

import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import javax.swing.*;
import javax.swing.plaf.LayerUI;
import javax.swing.table.*;

public class TableWaitLayerTest {
  private final String[] columnNames = {"String", "Integer", "Boolean"};
  private final Object[][] data = {
    {"aaa", 12, true}, {"bbb", 5, false}, {"ccc", 9, false},
  };
  private final DefaultTableModel model = new DefaultTableModel(data, columnNames) {
    @Override public Class<?> getColumnClass(int column) {
      return getValueAt(0, column).getClass();
    }
  };
  private final JTable table = new JTable(model);
  private final JButton startButton = new JButton();
  private final WaitLayerUI layerUI = new WaitLayerUI();
  public JComponent makeUI() {
    startButton.setAction(new AbstractAction("start") {
      @Override public void actionPerformed(ActionEvent e) {
        layerUI.start();
        startButton.setEnabled(false);
        SwingWorker<String, Object[]> worker = new SwingWorker<String, Object[]>() {
          @Override public String doInBackground() {
            int current = 0, lengthOfTask = 120;
            while(current<lengthOfTask && !isCancelled()) {
              try {
                Thread.sleep(50);
              } catch(InterruptedException ie) {
                return "Interrupted";
              }
              publish(new Object[] {"aaa", current++, false});
            }
            return "Done";
          }
          @Override protected void process(java.util.List<Object[]> chunks) {
            for(Object[] array: chunks) {
              model.addRow(array);
            }
            table.scrollRectToVisible(
                table.getCellRect(model.getRowCount()-1, 0, true));
          }
          @Override public void done() {
            layerUI.stop();
            startButton.setEnabled(true);
            String text = null;
            if(isCancelled()) {
              text = "Cancelled";
            } else {
              try {
                text = get();
              } catch(Exception ex) {
                ex.printStackTrace();
                text = "Exception";
              }
            }
          }
        };
        worker.execute();
      }
    });
    JPanel p = new JPanel(new BorderLayout());
    p.add(new JButton("dummy"), BorderLayout.NORTH);
    p.add(new JLayer<JComponent>(new JScrollPane(table), layerUI));
    p.add(startButton, BorderLayout.SOUTH);
    return p;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new TableWaitLayerTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

//http://docs.oracle.com/javase/tutorial/uiswing/misc/jlayer.html
//How to Decorate Components with the JLayer Class
//(The Java? Tutorials > Creating a GUI With JFC/Swing > Using Other Swing Features)
//TapTapTap.java
class WaitLayerUI extends LayerUI<JComponent> implements ActionListener {
  private boolean mIsRunning;
  private boolean mIsFadingOut;
  private Timer mTimer;

  private int mAngle;
  private int mFadeCount;
  private int mFadeLimit = 15;

  @Override public void paint (Graphics g, JComponent c) {
    int w = c.getWidth();
    int h = c.getHeight();

    // Paint the view.
    super.paint (g, c);

    if (!mIsRunning) {
      return;
    }

    Graphics2D g2 = (Graphics2D)g.create();

    float fade = (float)mFadeCount / (float)mFadeLimit;
    // Gray it out.
    Composite urComposite = g2.getComposite();
    g2.setComposite(AlphaComposite.getInstance(
                      AlphaComposite.SRC_OVER, .5f * fade));
    g2.fillRect(0, 0, w, h);
    g2.setComposite(urComposite);

    // Paint the wait indicator.
    int s = Math.min(w, h) / 5;
    int cx = w / 2;
    int cy = h / 2;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setStroke(
      new BasicStroke(s / 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
    g2.setPaint(Color.white);
    g2.rotate(Math.PI * mAngle / 180, cx, cy);
    for (int i = 0; i < 12; i++) {
      float scale = (11.0f - (float)i) / 11.0f;
      g2.drawLine(cx + s, cy, cx + s * 2, cy);
      g2.rotate(-Math.PI / 6, cx, cy);
      g2.setComposite(AlphaComposite.getInstance(
                        AlphaComposite.SRC_OVER, scale * fade));
    }

    g2.dispose();
  }

  @Override public void actionPerformed(ActionEvent e) {
    if (mIsRunning) {
      firePropertyChange("tick", 0, 1);
      mAngle += 3;
      if (mAngle >= 360) {
        mAngle = 0;
      }
      if (mIsFadingOut) {
        if (--mFadeCount == 0) {
          mIsRunning = false;
          mTimer.stop();
        }
      } else if (mFadeCount < mFadeLimit) {
        mFadeCount++;
      }
    }
  }

  public void start() {
    if (mIsRunning) {
      return;
    }
    // Run a thread for animation.
    mIsRunning = true;
    mIsFadingOut = false;
    mFadeCount = 0;
    int fps = 24;
    int tick = 1000 / fps;
    mTimer = new Timer(tick, this);
    mTimer.start();
  }

  public void stop() {
    mIsFadingOut = true;
  }

  @Override public void applyPropertyChange(PropertyChangeEvent pce, JLayer l) {
    if ("tick".equals(pce.getPropertyName())) {
      l.repaint();
    }
  }

  @Override public void installUI(JComponent c) {
    super.installUI(c);
    ((JLayer)c).setLayerEventMask(
      AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK |
      AWTEvent.MOUSE_WHEEL_EVENT_MASK | AWTEvent.KEY_EVENT_MASK |
      AWTEvent.FOCUS_EVENT_MASK | AWTEvent.COMPONENT_EVENT_MASK);
  }
  @Override public void uninstallUI(JComponent c) {
    ((JLayer)c).setLayerEventMask(0);
    super.uninstallUI(c);
  }
  @Override public void eventDispatched(AWTEvent e, JLayer<? extends JComponent> l) {
    if(mIsRunning && e instanceof InputEvent) {
      ((InputEvent)e).consume();
    }
  }
}
半﹌身腐败 2025-01-12 09:27:02

1) 半透明&莫代尔un_decorated JDialog(阻止父级的鼠标事件)

2)到GlassPane(可以阻止鼠标事件)

3)到JViewport

编辑

如果您的SQL解释器支持分页,则 ,然后拆分SQL ResultSet(5 - 20 块)并使用 JProgressBar 而不是循环Images

1) to Translucent & Modal & un_decorated JDialog (block Mouse event to the parent)

2) to GlassPane (can block Mouse event)

3) to JViewport

EDIT

if your SQL interpreter supports Paginations, then split SQL ResultSet (5 - 20 pieces) and use JProgressBar rather than cycled Images,

梦初启 2025-01-12 09:27:02

我认为玻璃板足以完成这项任务。它允许绘制窗口的内容。这是 教程 中的示例(红色圆圈是涂在按钮上):

在此处输入图像描述

I think Glass Pane fits enough for this task. It allows to draw over content of window. Here is the example from tutorial (red circle is painted over button):

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文