From e7a3d98dd09222711001efe65e128ead340e1369 Mon Sep 17 00:00:00 2001 From: rattatwinko Date: Wed, 14 Jan 2026 20:55:45 +0100 Subject: [PATCH] Quality of Life changes to the viewer changed: / SwingIFrame ; Some new methodes for setting bg color, and fullscreen, keybinds are "F11" and "B" / WebcamCaptureLoop.java ; Safety is key! --- rattatwinko --- src/main/java/io/swtc/SwingIFrame.java | 88 +++++++++++++++++++ .../swtc/proccessing/WebcamCaptureLoop.java | 34 +++++-- 2 files changed, 115 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/swtc/SwingIFrame.java b/src/main/java/io/swtc/SwingIFrame.java index a788ff1..f2f76b2 100644 --- a/src/main/java/io/swtc/SwingIFrame.java +++ b/src/main/java/io/swtc/SwingIFrame.java @@ -10,6 +10,7 @@ import javax.swing.*; import javax.swing.border.EmptyBorder; import javax.swing.border.TitledBorder; import java.awt.*; +import java.awt.event.ActionEvent; import java.awt.image.BufferedImage; import java.io.File; import java.text.SimpleDateFormat; @@ -24,14 +25,28 @@ import java.util.Date; public class SwingIFrame { private final JFrame mainFrame; private final JDesktopPane desktopPane; + private boolean fullscreen = false; + private Rectangle windowedBounds; + private boolean blackbg = false; + private final Color defDesktopBg; + private final Color bgcolor; public SwingIFrame() { mainFrame = new JFrame("viewer"); mainFrame.setSize(1280,720); mainFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + + // this is good on the eyes for long periods of times, + // i would have used #4B9EA0, which is also easy on the eyes + bgcolor = Color.decode("#1e1e1e"); + desktopPane = new JDesktopPane(); desktopPane.setBackground(Color.WHITE); + defDesktopBg = desktopPane.getBackground(); mainFrame.add(desktopPane, BorderLayout.CENTER); + + setupFullscreenToggle(); + setupBlackBg(); } public void addCameraInternalFrame(Webcam webcam) { @@ -73,6 +88,79 @@ public class SwingIFrame { captureLoop.start(); } + private void setupBlackBg() { + JRootPane root = mainFrame.getRootPane(); + + root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW) + .put(KeyStroke.getKeyStroke("B"), "toggleBlackBg"); + + root.getActionMap().put("toggleBlackBg", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + setbgblack(); + } + }); + } + /* Setup F11 for Fullscreen */ + private void setupFullscreenToggle() { + JRootPane root = mainFrame.getRootPane(); + + root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW) + .put(KeyStroke.getKeyStroke("F11"), "toggleFullscreen"); + + root.getActionMap().put("toggleFullscreen", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + toggleFullscreen(); + } + }); + } + + private void setbgblack() { + if (!blackbg) { + // easy stuff here, just setting the bg to the private color + desktopPane.setBackground(bgcolor); + updateInternalFrameBg(bgcolor); + } else { + desktopPane.setBackground(defDesktopBg); + updateInternalFrameBg(null); + } + blackbg = !blackbg; + } + + private void updateInternalFrameBg(Color bg) { + for (JInternalFrame frame : desktopPane.getAllFrames()) { + Container content = frame.getContentPane(); + if (bg != null) { + content.setBackground(bg); + } else content.setBackground(null); // restore default + content.repaint(); + } + } + + private void toggleFullscreen() { + if (!fullscreen) { + // We set the window to borderless windowed mode, so it doesnt + // lag like shit when we drag windows around, which is annoying + windowedBounds = mainFrame.getBounds(); + mainFrame.dispose(); + mainFrame.setUndecorated(true); + mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH); + mainFrame.setVisible(true); + } else { + // do the opposite + mainFrame.dispose(); + mainFrame.setUndecorated(false); + mainFrame.setExtendedState(JFrame.NORMAL); + mainFrame.setBounds(windowedBounds); + mainFrame.setVisible(true); + } + + fullscreen = !fullscreen; + } + + + private JPanel createCapturePanel(CameraPanel cameraPanel, Webcam webcam) { JPanel panel = new JPanel(new BorderLayout(10, 10)); panel.setBorder(new EmptyBorder(15, 15, 15, 15)); diff --git a/src/main/java/io/swtc/proccessing/WebcamCaptureLoop.java b/src/main/java/io/swtc/proccessing/WebcamCaptureLoop.java index 6e9283d..77ba110 100644 --- a/src/main/java/io/swtc/proccessing/WebcamCaptureLoop.java +++ b/src/main/java/io/swtc/proccessing/WebcamCaptureLoop.java @@ -5,13 +5,15 @@ import com.github.sarxos.webcam.WebcamException; import java.awt.Dimension; import java.awt.image.BufferedImage; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; -import javax.swing.JOptionPane; +import javax.swing.*; public class WebcamCaptureLoop { private final Webcam webcam; private final Consumer onFrameCaptured; private volatile boolean running = false; + private final AtomicBoolean cleanedUp = new AtomicBoolean(false); public WebcamCaptureLoop(Webcam webcam, Consumer onFrameCaptured) { this.webcam = webcam; @@ -64,22 +66,40 @@ public class WebcamCaptureLoop { captureThread.start(); } - // method for cleaning up + /** + * Safely release webcam + */ private synchronized void cleanup() { + if (!cleanedUp.compareAndSet(false, true)) { + return; + } + + boolean success = false; + try { - // if the camera is open try to cloes it! - webcam.close(); + if (webcam.isOpen()) + webcam.close(); + + success = true; + } catch (WebcamException exception) { + SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog( null, "Cleanup failed \nWebCamException@"+exception.getMessage(), "WebCamException", - JOptionPane.ERROR_MESSAGE - ); + JOptionPane.WARNING_MESSAGE // changed to warning, its better tbh + )); + } finally { + if (!success) + cleanedUp.set(false); } - } + /** + * Arguments: null (or just none) + * What does this method do? : Sets CameraThreads running flag to false and calls cleanup(); + */ public void stop() { running = false; cleanup();