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

@@ -1,7 +1,16 @@
package io.swtc;
public class Main {
public static void main(String[] args) {
// very simple main, so that we can start the manager!
CCTVManager.main(args);
for (int i = 0; i < args.length; i++) {
System.out.println("Arg " + i + ": " + args[i]);
}
if (args.length > 0 && "swing".equalsIgnoreCase(args[0])) {
SwingCCTVManager.main(new String[0]);
} else {
CCTVManager.main(new String[0]);
}
}
}
}

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());
}
}

View File

@@ -0,0 +1,82 @@
package io.swtc;
import com.github.sarxos.webcam.Webcam;
import io.swtc.proccessing.WebcamCaptureLoop;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
public class SwingCameraWindow {
private final JFrame frame;
private final CameraPanel cameraPanel;
private final WebcamCaptureLoop captureLoop;
public SwingCameraWindow(Webcam webcam) {
this.frame = new JFrame("scctv@" + webcam.getName());
this.frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
this.frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// clean shit up
frame.dispose();
}
});
this.cameraPanel = new CameraPanel();
this.frame.add(cameraPanel);
this.frame.pack();
this.frame.setSize(640, 480);
this.captureLoop = new WebcamCaptureLoop(webcam, (BufferedImage img) -> {
SwingUtilities.invokeLater(() -> {
cameraPanel.setImage(img);
});
});
this.frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
captureLoop.stop();
}
});
}
public void open() {
frame.setVisible(true);
captureLoop.start();
}
private static class CameraPanel extends JPanel {
private BufferedImage currentImage;
public void setImage(BufferedImage img) {
this.currentImage = img;
this.repaint(); // Triggers paintComponent
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (currentImage != null) {
// Draw the image scaled to the panel size
g.drawImage(currentImage, 0, 0, getWidth(), getHeight(), null);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
// init in edt
Webcam webcam = Webcam.getDefault();
if (webcam != null) {
SwingCameraWindow window = new SwingCameraWindow(webcam);
window.open();
} else {
System.err.println("No webcam found!");
}
});
}
}

View File

@@ -44,7 +44,11 @@ public class WebcamCaptureLoop {
break;
}
}
webcam.close();
try {
webcam.close();
} catch (IllegalStateException e) {
e.printStackTrace();
}
});
captureThread.setName("cam_cap_thread");
captureThread.start();