some swing stuff cause swt is heavy and swing isnt

+ SwingCameraWindow
+ SwingCCTVManager

---
fixes in WebcamCaptureLoop.java : Include thread safety, and some more stuff which is needed for Swing components.

Planning on deprecating SWT in general
This commit is contained in:
2026-01-11 21:09:51 +01:00
parent ddba427205
commit 965bed6801
7 changed files with 432 additions and 4 deletions

View File

@@ -0,0 +1,199 @@
package io.swtc;
import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamCompositeDriver;
import com.github.sarxos.webcam.ds.buildin.WebcamDefaultDriver;
import com.github.sarxos.webcam.ds.ipcam.IpCamDeviceRegistry;
import com.github.sarxos.webcam.ds.ipcam.IpCamDriver;
import com.github.sarxos.webcam.ds.ipcam.IpCamMode;
import io.swtc.networking.CameraConfig;
import io.swtc.networking.CameraSettings;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.MalformedURLException;
import java.util.List;
public class SwingCCTVManager {
static {
Webcam.setDriver(new WebcamCompositeDriver() {{
add(new WebcamDefaultDriver());
add(new IpCamDriver());
}});
loadSavedCameras();
}
private final JFrame frame;
private final JTable deviceTable;
private final DefaultTableModel tableModel;
private Timer autoRefreshTimer;
public SwingCCTVManager() {
frame = new JFrame("dashboard");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000, 600);
String[] columns = {"Status", "Device Name", "Type", "Resolution", "Address"};
tableModel = new DefaultTableModel(columns, 0) {
@Override public boolean isCellEditable(int r, int c) { return false; }
};
deviceTable = new JTable(tableModel);
setupTableAppearance();
deviceTable.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if (e.getClickCount() == 2 && deviceTable.getSelectedRow() != -1) {
launchSelected();
}
if (SwingUtilities.isRightMouseButton(e)) {
showContextMenu(e);
}
}
});
JToolBar toolBar = new JToolBar();
JButton btnAdd = new JButton("Add IP Cam");
JButton btnLaunch = new JButton("Launch Stream");
toolBar.add(btnAdd);
toolBar.addSeparator();
toolBar.add(btnLaunch);
frame.add(toolBar, BorderLayout.NORTH);
frame.add(new JScrollPane(deviceTable), BorderLayout.CENTER);
btnAdd.addActionListener(e -> showAddCameraDialog());
btnLaunch.addActionListener(e -> launchSelected());
startAutoRefresh();
refreshTable();
}
private void setupTableAppearance() {
deviceTable.getColumnModel().getColumn(0).setMaxWidth(80); // Status column
deviceTable.setRowHeight(30);
// Custom Renderer for Status Colors
deviceTable.getColumnModel().getColumn(0).setCellRenderer(new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable t, Object v, boolean s, boolean f, int r, int c) {
Component comp = super.getTableCellRendererComponent(t, v, s, f, r, c);
if ("ONLINE".equals(v)) comp.setForeground(new Color(0, 150, 0));
else comp.setForeground(Color.RED);
setHorizontalAlignment(JLabel.CENTER);
return comp;
}
});
}
private void startAutoRefresh() {
autoRefreshTimer = new Timer(5000, e -> refreshTable());
autoRefreshTimer.start();
}
private void refreshTable() {
int selectedRow = deviceTable.getSelectedRow();
tableModel.setRowCount(0);
List<Webcam> webcams = Webcam.getWebcams();
for (Webcam w : webcams) {
boolean isIp = w.getDevice().getClass().getSimpleName().contains("IpCam");
String status = w.getDevice() != null ? "ONLINE" : "OFFLINE";
tableModel.addRow(new Object[]{
status,
w.getName(),
isIp ? "IP Stream" : "USB Hardware",
w.getViewSize().width + "x" + w.getViewSize().height,
isIp ? "Network" : "Local"
});
}
if (selectedRow != -1 && selectedRow < tableModel.getRowCount()) {
deviceTable.setRowSelectionInterval(selectedRow, selectedRow);
}
}
private void showContextMenu(MouseEvent e) {
int row = deviceTable.rowAtPoint(e.getPoint());
deviceTable.setRowSelectionInterval(row, row);
JPopupMenu menu = new JPopupMenu();
JMenuItem launch = new JMenuItem("Launch Live Stream");
JMenuItem delete = new JMenuItem("Remove Device");
launch.addActionListener(al -> launchSelected());
delete.addActionListener(al -> deleteSelected());
menu.add(launch);
menu.addSeparator();
menu.add(delete);
menu.show(deviceTable, e.getX(), e.getY());
}
private void launchSelected() {
int row = deviceTable.getSelectedRow();
if (row == -1) return;
String name = (String) tableModel.getValueAt(row, 1);
Webcam selected = Webcam.getWebcams().stream()
.filter(w -> w.getName().equals(name))
.findFirst().orElse(null);
if (selected != null) {
new Thread(() -> new SwingCameraWindow(selected).open()).start();
}
}
private void deleteSelected() {
int row = deviceTable.getSelectedRow();
String name = (String) tableModel.getValueAt(row, 1);
if (name.toLowerCase().contains("usb")) return;
CameraSettings.delete(name);
IpCamDeviceRegistry.unregister(name);
refreshTable();
}
private static void loadSavedCameras() {
for (CameraConfig config : CameraSettings.load()) {
try {
IpCamDeviceRegistry.register(config.getName(), config.getUrl(), IpCamMode.PUSH);
} catch (MalformedURLException e) { e.printStackTrace(); }
}
}
private void showAddCameraDialog() {
JPanel p = new JPanel(new GridLayout(2, 2, 5, 5));
JTextField n = new JTextField();
JTextField u = new JTextField();
p.add(new JLabel("Name:")); p.add(n);
p.add(new JLabel("URL:")); p.add(u);
int result = JOptionPane.showConfirmDialog(frame, p, "Register IP Camera", JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
try {
IpCamDeviceRegistry.register(n.getText(), u.getText(), IpCamMode.PUSH);
CameraSettings.save(new CameraConfig(n.getText(), u.getText()));
refreshTable();
} catch (Exception ex) {
JOptionPane.showMessageDialog(frame, "Error: " + ex.getMessage());
}
}
}
public void open() {
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new SwingCCTVManager().open());
}
}