I am having a bit of problem with changing and Icon in a JLabel dynamically. First of all, what i am trying to do is basically simulating a screen sharing operation. On the client side, I am taking screenshots every second, sending them to the server. On the server side, I am trying to open these pictures in a simple GUI.
I am able to send the pictures without problem and I am also able to get them without problem as well. However, the GUI code I have written cannot open the pictures. More specifically, If there is a picture, it is able to open it, but it does not open another picture that has come.
What I am doing in the server side is, as soon as a picture gets to the server, I am saving it with a predetermined name. And then I am able to open the picture with Windows' own picture photo viewer. In fact, as soon as a new picture comes, photo viewer updates itself and shows the new screenshot.
However, I am having trouble opening the screenshots in a JFrame. I have written a program to take the screenshots in jpg format, send them to the server and then open them in a GUI. however i am having problems with the opening in the GUI part. From what I have understood, it does not open the files that are coming by from the client.
Below are my codes, any help will be much appreciated.
Server side,
package ScreenCap;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import FileServer.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import test.TsgIcons;
/**
*
* #author busra
*/
public class ScreenCapServer extends Thread{
String filePath;
int portNumber;
FileServer screenCapServer;
ServerSocket getFileServer;
Socket getFile;
InputStream in;
FileOutputStream fileOutputStream;
TsgIcons screenShotIcons;
public ScreenCapServer(String path, int port) {
this.filePath = path;
this.portNumber = port;
this.screenShotIcons = new TsgIcons();
}
public static void waitTime(long millisecond){
long max = millisecond;
for(long i = 0; i < max; i++){
for(long j = 0; j < max; j++){
}
}
}
public void run() {
while(true) {
try {
for(int i = 0; i < 10; i++) {
getFileServer = new ServerSocket(portNumber);
getFile = getFileServer.accept();
in = getFile.getInputStream();
fileOutputStream = new FileOutputStream(filePath + "\\" + i + ".jpg");
byte [] buffer = new byte[64*1024];
int bytesRead = 0;
while ( (bytesRead = in.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, bytesRead);
}
in.close();
fileOutputStream.close();
getFileServer.close();
screenShotIcons.update();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
GUI,
package test;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class TsgIcons extends JFrame implements ActionListener {
protected Timer timer;
protected JLabel viewIcon;
private String[] SMILEY = {"orig_screen"};
private String BUTTON = "Button";
private int timeCount;
private int iconNumber;
private String image;
public TsgIcons() {
this(1, 100);
}
public TsgIcons(int initialTime, int delay) {
super("TSG Smileys");
this.timeCount = initialTime;
this.iconNumber = this.timeCount % this.SMILEY.length;
this.image = "TransferredScreenShots\\" + this.SMILEY[this.iconNumber] + ".jpg";
this.viewIcon = new JLabel();
this.viewIcon.setIcon(new javax.swing.ImageIcon(this.image));
this.timer = new Timer(delay, this);
this.init();
}
protected void init() {
JButton button = new JButton("Start / Stop");
button.setActionCommand(BUTTON);
button.addActionListener(this);
this.viewIcon.setHorizontalAlignment(JLabel.CENTER);
this.getContentPane().add(button, BorderLayout.SOUTH);
this.getContentPane().add(this.viewIcon, BorderLayout.CENTER);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocation(250, 250);
this.pack();
this.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if ( BUTTON.equals(e.getActionCommand()) ) { // test if the button clicked
if ( this.timer.isRunning() ) {
this.timer.stop();
} else {
this.timer.start();
}
} else
{ this.timeCount++;
this.iconNumber = this.timeCount % this.SMILEY.length;
this.image = "TransferredScreenShots\\" + this.SMILEY[this.iconNumber] + ".jpg";
this.viewIcon.setIcon(new javax.swing.ImageIcon(this.image));
}
}
public void update() {
this.timeCount++;
this.iconNumber = this.timeCount % this.SMILEY.length;
this.image = "TransferredScreenShots\\" + this.SMILEY[this.iconNumber] + ".jpg";
this.viewIcon.setIcon(new javax.swing.ImageIcon(this.image));
}
public static void main(String argv []) {
new TsgIcons();
}
}
Related
Im trying to build an Installer/Updater for a project im working on.
My only problem im facing is that my variable of my progess bar doesn't want to be displayed in a label :C.
I already looked up and found an answer from Sebastian who said
myLabel.textProperty().bind(valueProperty); should work but ... well you guess the outcome.
Eclipse says I have to change the type of my int to: ObservableValue<? extends String> and when I changed it it says I have to change it back to int. I dont know what I have to do now ://
EDIT: Full code of my controller class
package application;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
public class Controller {
#FXML
ProgressBar pb;
Label progText;
public void install(){
new Thread(new Runnable() {
#Override public void run() {
download();
}}).start();
};
public void load(){
new Thread(new Runnable() {
#Override public void run() {
download();
Unzip.extract();
System.out.println("Finished");
}}).start();
};
public void download(){
try {
System.out.println("Start");
URL url = new URL("https://www.dropbox.com/s/27d4us64oqifuph/modpack.zip?dl=1");
HttpURLConnection httpConnection = (HttpURLConnection) (url.openConnection());
long completeFileSize = httpConnection.getContentLength();
java.io.BufferedInputStream in = new java.io.BufferedInputStream(httpConnection.getInputStream());
java.io.FileOutputStream fos = new java.io.FileOutputStream(
"modpack.zip");
java.io.BufferedOutputStream bout = new BufferedOutputStream(
fos, 1024);
byte[] data = new byte[1024];
long downloadedFileSize = 0;
int x = 0;
while ((x = in.read(data, 0, 1024)) >= 0) {
downloadedFileSize += x;
//calculate progress
int cp = (int) ((((double)downloadedFileSize) / ((double)completeFileSize)) * 10000);
DoubleProperty progress = new SimpleDoubleProperty(0);
// update progress bar
pb.setProgress(cp*0.0001);
progress.setValue(cp*0.0001);
progText.textProperty().bind(progress.asString());
bout.write(data, 0, x);
}
bout.close();
in.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
};
}
Create a DoubleProperty that is bound to the label and is updated when you update the progressbar.
DoubleProperty progress = new SimpleDoubleProperty(0);
progText.textProperty().bind(progress.asString());
...
// update progress bar
pb.setProgress(cp*0.0001);
progress.setValue(cp*0.0001)
In a Swing application, I sometimes need to support read-only access to large, line-oriented text files that are slow to load: logs, dumps, traces, etc. For small amounts of data, a suitable Document and JTextComponent are fine, as shown here. I understand the human limitations of browsing large amounts of data, but the problematic stuff seems like it's always in the biggest file. Is there any practical alternative for larger amounts of text in the 10-100 megabyte, million-line range?
Because of the size, you'll surely want to load the file in the background to avoid blocking the event dispatch thread; SwingWorker is a common choice. Instead of using a Document, consider updating a TableModel and displaying the lines of text in the rows of a JTable. This offers several advantages:
Results will begin appearing immediately, and there will be reduced perceived latency.
JTable uses the flyweight pattern for rendering, which scales well into the multi-megabyte, million-line range.
You can parse the input as it is being read to create an arbitrary column structure.
You can leverage the sorting and filtering features of JTable, for example.
You can use TablePopupEditor to focus on a single line.
Addendum: The example below uses DefaultTableModel for convenience. To reduce overhead, extend AbstractTableModel and manage a List<String> or List<RowData>, as shown here. The example displays indeterminate progress; changes to display intermediate progress are shown here.
Code:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
/**
* #see https://stackoverflow.com/a/25526869/230513
*/
public class DisplayLog {
private static final String NAME = "/var/log/install.log";
private static class LogWorker extends SwingWorker<TableModel, String> {
private final File file;
private final DefaultTableModel model;
private LogWorker(File file, DefaultTableModel model) {
this.file = file;
this.model = model;
model.setColumnIdentifiers(new Object[]{file.getAbsolutePath()});
}
#Override
protected TableModel doInBackground() throws Exception {
BufferedReader br = new BufferedReader(new FileReader(file));
String s;
while ((s = br.readLine()) != null) {
publish(s);
}
return model;
}
#Override
protected void process(List<String> chunks) {
for (String s : chunks) {
model.addRow(new Object[]{s});
}
}
}
private void display() {
JFrame f = new JFrame("DisplayLog");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DefaultTableModel model = new DefaultTableModel();
JTable table = new JTable(model);
JProgressBar jpb = new JProgressBar();
f.add(jpb, BorderLayout.NORTH);
f.add(new JScrollPane(table));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
LogWorker lw = new LogWorker(new File(NAME), model);
lw.addPropertyChangeListener((PropertyChangeEvent e) -> {
SwingWorker.StateValue s = (SwingWorker.StateValue) e.getNewValue();
jpb.setIndeterminate(s.equals(SwingWorker.StateValue.STARTED));
});
lw.execute();
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new DisplayLog().display();
});
}
}
I would separate the problem.
The first one is model - Document building speed
The second is the Document rendering - building tree of views to represent the Document.
A question is whether you need font effects like keywords colorizing?
I would start from Document building part. IMHO reading the file via EditorKit.read() should be fast even for big files. I would use the PainDocument for the purpose and check whether the pure model is built fast enough for your application. If yes it's fine just use the Document as model. If not implement your own Document interface because AbstractDocument has plenty of methods for update processing (e.g. writeLock).
When we have the Document loading fast enough we have to solve the Document rendering. BY default the views used in javax.swing.text are really flexible. They are designed as base classes to be extended - thus has a lot of code we don't need. E.g. measuring.
For the feature I would use Monospaced font, we don't need wrap so measurements of the view widht is fast = longest row char count * char widht.
The height is also char height * amount of lines.
So our PLainTextViewReplacement is really fast. Also we don't have to render the whole view but just a fragment visible in our scroll pane. Thus rendering could be mmuch much faster.
Of course there should be a lot of work to provide correct caret navigation, selection etc.
As I was struggeling with a similar use case I implemented a simple paging solution. It is far from perfect but works maybe someone finds it helpful.
In combination with a jtextarea it works ok but with a JEditorPane the performance is miserable.
If someone comes up with a better solution I would like to know about.
package net.ifao.tools.arcticrequester.gui.panel;
import java.awt.Adjustable;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.StringReader;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
import javax.swing.text.Document;
import javax.swing.text.EditorKit;
import javax.swing.text.JTextComponent;
/**
* A class that manages the visibility of file content visualized with a textarea within a scrollbar.
* Approx. 2050 lines from the file are visible at a time. Data is loaded from a file and
* displayed while the user is scrolling. The chunks are loaded dynamically.
*
* #author dostricki
*
*/
public class VisibilityManager
implements AdjustmentListener
{
private int lastLoadedLineFrom;
private int lastLoadedLineTo;
private int numberOfLines = 0;
private File file;
private boolean enabled = false;
private boolean showLines = false;
// load 1000 lines before the first visible line
// and 1000 lines after the last vissible line
private static final int LOAD_LINES_BEFORE_AND_AFTER_VIEWPORT = 1000;
// margin until when no load is triggered.
// moving the viewport more then 900 lines up or down should trigger a reload
private static final int VIEWPORT_LINES_MOVE_THRASHOLD = 900;
private JScrollPane scrollPane;
private JTextComponent textComponent;
private final BlockingQueue<Adjustable> queue;
public VisibilityManager(JScrollPane scrollPane, JTextComponent textArea)
{
this.scrollPane = scrollPane;
this.textComponent = textArea;
queue = new LinkedBlockingDeque<>();
startConsumer();
scrollPane.getVerticalScrollBar().addAdjustmentListener(this);
}
private void startConsumer()
{
Thread scrollEventConsumer = new Thread()
{
#Override
public void run()
{
while (true) {
try {
// if multiple events occured just process one
queue.take();
if (!queue.isEmpty()) {
List<Adjustable> events = new ArrayList<>();
queue.drainTo(events);
//System.out.println("Handling scroll event. " + events.size() + " queued events dropped");
}
doHandleScrollEvent();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
scrollEventConsumer.start();
}
public void setFile(File file)
{
this.file = file;
try {
this.numberOfLines = countNumberOfLines(file);
}
catch (IOException e1) {
e1.printStackTrace();
}
int showLineMax = Math.min(getNumberOfLines(), 100);
// show the first chunk immediately
showLinesBuffererdReader(1, showLineMax, 0);
this.enabled = true;
}
/**
* precalculates the number of lines in the document - necessary
* to replace the correct amount of preceeding and following
* lines with EOL's so that the height of the scrollpane does never change.
*
* #param file
* #return
* #throws IOException
*/
private int countNumberOfLines(File file)
throws IOException
{
int numberOfLines = 0;
//#formatter:off
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),StandardCharsets.UTF_8));) {
while (reader.ready()) {
reader.readLine();
++numberOfLines;
}
}
//#formatter:on
return numberOfLines;
}
/****************************************
* Getter
****************************************/
public int getNumberOfLines()
{
return numberOfLines;
}
public int getNumberOfLinesBuffer()
{
return LOAD_LINES_BEFORE_AND_AFTER_VIEWPORT;
}
public boolean isEnabled()
{
return enabled;
}
/****************************************
* Setter
****************************************/
public void setLastLoadedLines(int lineFrom, int lineTo)
{
this.lastLoadedLineFrom = lineFrom;
this.lastLoadedLineTo = lineTo;
}
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}
public void setShowLines(boolean showLines)
{
this.showLines = showLines;
}
/****************************************
* Calculation
****************************************/
private boolean needsUpdate(int fromLine, int toLine)
{
boolean isBefore = fromLine < (this.lastLoadedLineFrom - VIEWPORT_LINES_MOVE_THRASHOLD);
boolean isAfter = toLine > (this.lastLoadedLineTo + VIEWPORT_LINES_MOVE_THRASHOLD);
if (isBefore || isAfter) {
return true;
} else {
return false;
}
}
private void showLinesBuffererdReader(int from, int to, int firstLineVisible)
{
//load also the buffer lines before
from = from - getNumberOfLinesBuffer();
//make sure it's valid
from = Math.max(1, from);
// load also the buffer lines after
to = to + getNumberOfLinesBuffer();
//make sure it's valid
to = Math.min(getNumberOfLines(), to);
FileChannel fileChannel = null;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)))) {
StringBuffer content = new StringBuffer();
int newCaretPosition = 0;
// fill leading empty lines
for (long i = 1; i < from; ++i) {
if (i == firstLineVisible) {
newCaretPosition = content.length() + 1;
}
if (showLines) {
content.append(i).append(": ");
}
content.append('\n');
}
// read/write lines with content
int j = 0;
while (reader.ready() && j <= to) {
++j;
String line = reader.readLine();
if (j >= from && j <= to) {
if (j == firstLineVisible) {
newCaretPosition = content.length() + 1;
}
if (showLines) {
content.append(j).append(": ");
}
content.append(line).append('\n');
}
}
// fill trailing empty lines
for (int i = to + 1; i <= getNumberOfLines(); ++i) {
if (i == firstLineVisible) {
newCaretPosition = content.length() + 1;
}
if (showLines) {
content.append(i).append(": ");
}
content.append('\n');
}
updateTextInUI(content);
// workaround for page up/down - it changes the caret position
// so we are re-setting it to the first visible line
// scrolling by scrollbars does not change the caret
//textComponent.setCaretPosition(newCaretPosition);
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if (fileChannel != null) {
fileChannel.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* #param content
* #throws IOException
*/
private void updateTextInUI(StringBuffer content)
throws IOException
{
if (textComponent instanceof JEditorPane) {
JEditorPane edit = ((JEditorPane) textComponent);
EditorKit editorKit = edit.getEditorKit();
Document createDefaultDocument = editorKit.createDefaultDocument();
createDefaultDocument.putProperty("IgnoreCharsetDirective", Boolean.TRUE);
try {
editorKit.read(new StringReader(content.toString()), createDefaultDocument, 0);
}
catch (Exception e) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(out));
edit.setText(new String(out.toByteArray()));
}
edit.setDocument(createDefaultDocument);
} else {
textComponent.setText(content.toString());
}
}
/****************************************
* Eventing
****************************************/
/**
* fired when scrolling happens in any of the cases and ways.
* Events are cached through a queue so that simultanious events
* don't trigger unnecessary update actions
* #see java.awt.event.AdjustmentListener#adjustmentValueChanged(java.awt.event.AdjustmentEvent)
*/
#Override
public void adjustmentValueChanged(AdjustmentEvent evt)
{
Adjustable source = evt.getAdjustable();
if (evt.getValueIsAdjusting()) {
return;
}
if (source != null) {
try {
queue.put(source);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void doHandleScrollEvent()
{
// determine which lines to request to be loaded into the
int height = this.scrollPane.getVerticalScrollBar().getMaximum();
int lines = getNumberOfLines();
if (lines == 0) {
return;
}
float heightPerLine = height / lines;
int visibleLines = Math.round(this.scrollPane.getVerticalScrollBar().getVisibleAmount() / heightPerLine);
int firstLineVisible = (int) Math.ceil(this.scrollPane.getVerticalScrollBar().getValue() / heightPerLine);
int fromLine = Math.max(firstLineVisible, 1);
if (fromLine > lines) {
fromLine = lines;
}
int toLine = Math.min(firstLineVisible + visibleLines, lines);
if (needsUpdate(fromLine, toLine)) {
if (enabled) {
setLastLoadedLines(fromLine, toLine);
showLinesBuffererdReader(fromLine, toLine, firstLineVisible);
}
}
}
}
usage:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.text.DefaultCaret;
import net.ifao.tools.arcticrequester.gui.panel.VisibilityManager;
public class TestFrame
extends JFrame
implements MouseListener
{
private VisibilityManager visibilityManager;
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
try {
TestFrame frame = new TestFrame();
frame.setVisible(true);
}
catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public TestFrame()
{
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 650, 500);
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new BorderLayout(0, 0));
JTextArea textArea = new JTextArea();
textArea.setEditable(false);
textArea.addMouseListener(this);
textArea.setAutoscrolls(false);
textArea.setCaretPosition(0);
DefaultCaret caret = (DefaultCaret) textArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
JScrollPane scrollPane = new JScrollPane(textArea);
contentPane.add(scrollPane);
visibilityManager = new VisibilityManager(scrollPane, textArea);
visibilityManager.setShowLines(true);
File file = new File("C:/iFAO/workspaces/polaris2/git/requester/ArcticRequester/src/test/java/responseview_20200603.tmp");
visibilityManager.setFile(file);
this.dispose();
}
/**
* #see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
*/
#Override
public void mouseClicked(MouseEvent e)
{
boolean doScroll = !visibilityManager.isEnabled();
this.visibilityManager.setEnabled(doScroll);
System.out.println("scrolling set to " + doScroll);
}
/**
* #see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
*/
#Override
public void mousePressed(MouseEvent e)
{
// TODO Auto-generated method stub
}
/**
* #see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
*/
#Override
public void mouseReleased(MouseEvent e)
{
// TODO Auto-generated method stub
}
/**
* #see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
*/
#Override
public void mouseEntered(MouseEvent e)
{
// TODO Auto-generated method stub
}
/**
* #see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
*/
#Override
public void mouseExited(MouseEvent e)
{
// TODO Auto-generated method stub
}
}
First, everyone needs to know i'm relatively new to Java coding. To be more precise i'm completely new to Object Oriented Programming.
To the question.
I am trying to create a download class that updates a progress bar it was given to show its progress. And possibly anything else I decide to give it in the future to update.
The issue currently is that, in my head, this shouldn't work. I can do anything i want on the "main" method and the GUI is still responsive and quick. In my experience in past programming, this is not possible unless i thread the GUI. Why is this?
Since it works, is this ok to do it this way?
Class Main
package atomicElectronics;
import java.io.IOException;
import atomicElectronics.physical.AtomFrame;
import atomicElectronics.utility.Download;
public class Initial {
static AtomFrame atomLauncher;
public static void main(String[] args) {
atomLauncher = new AtomFrame();
atomLauncher.start();
System.out.println(Integer.MAX_VALUE);
Download theDownload = new Download();
theDownload.fileProgressBar(atomLauncher.progressBar);
try {
theDownload.exicute("http://download.videolan.org/pub/videolan/vlc/last/win64/vlc-2.1.3-win64.exe", "C:\\Users\\TrinaryAtom\\AppData\\Roaming");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Add Download Methods
// theDownload.updateBarTotal(JProgressBar);
// theDownload.updateLabelSpeed(String);
// theDownload.updateLabelTotal(String);
// theDownload.addFile(File);
// theDownload.addFiles(Files);
}
}
Class AtomFrame
package atomicElectronics.physical;
import javax.swing.JFrame;
import java.awt.FlowLayout;
import javax.swing.JProgressBar;
public class AtomFrame extends JFrame{
public JProgressBar progressBar;
private static final long serialVersionUID = 4010489530693307355L;
public static void main(String[] args){
AtomFrame testFrame = new AtomFrame();
testFrame.start();
}
public AtomFrame(){
initializeComponents();
}
public void initializeComponents(){
this.setSize(400, 400);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Atom Launcher");
this.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
progressBar = new JProgressBar();
this.add(progressBar);
//this.pack();
}
public void start() {
this.setVisible(true);
}
public void close() {
this.dispose();
}
}
Class Download
package atomicElectronics.utility;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.swing.JProgressBar;
public class Download {
private static final int BUFFER_SIZE = 4096;
private JProgressBar fileProgressBar;
public Download() {
}
public void fileProgressBar(JProgressBar fileBar) {
fileProgressBar = fileBar;
}
public void exicute(String fileURL, String saveDir) throws IOException {
URL url = new URL(fileURL);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
int responseCode = httpConn.getResponseCode();
// always check HTTP response code first
if (responseCode == HttpURLConnection.HTTP_OK) {
String fileName = "";
String disposition = httpConn.getHeaderField("Content-Disposition");
String contentType = httpConn.getContentType();
double contentLength = httpConn.getContentLength();
if (disposition != null) {
// extracts file name from header field
int index = disposition.indexOf("filename=");
if (index > 0) {
fileName = disposition.substring(index + 9,
disposition.length());
}
} else {
// extracts file name from URL
fileName = fileURL.substring(fileURL.lastIndexOf("/") + 1,
fileURL.length());
}
System.out.println("Content-Type = " + contentType);
System.out.println("Content-Disposition = " + disposition);
System.out.println("Content-Length = " + contentLength);
System.out.println("fileName = " + fileName);
// opens input stream from the HTTP connection
InputStream inputStream = httpConn.getInputStream();
String saveFilePath = saveDir + File.separator + fileName;
// opens an output stream to save into file
FileOutputStream outputStream = new FileOutputStream(saveFilePath);
double totalRead = 0;
int bytesRead = -1;
byte[] buffer = new byte[BUFFER_SIZE];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
totalRead += bytesRead;
System.out.println((totalRead / contentLength) * 100);
fileProgressBar.setValue((int)((totalRead / contentLength) * 100));
}
outputStream.close();
inputStream.close();
System.out.println("File downloaded");
} else {
System.out.println("No file to download. Server replied HTTP code: " + responseCode);
}
httpConn.disconnect();
}
}
Suggestions:
Use a SwingWorker to do your background thread work.
Inside your SwingWorker, set its progress "bound" property via setProgress(int progress). The value should be between 1 and 100.
Don't have your SwingWorker/file downloader hold the JProgressBar or any Swing components.
Add a PropertyChangeListener to your SwingWorker and monitor changes in the progress property.
Never make your Swing fields (or most and and all fields) public. Limit access, and instead change object state via methods.
Read the tutorial Concurrency in Swing for the necessary details.
For example, the code below is a gross simplification and downloads no files, but should give you the idea:
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Random;
import javax.swing.*;
public class Initial {
static AtomFrame atomLauncher;
public static void main(String[] args) {
atomLauncher = new AtomFrame();
atomLauncher.start();
System.out.println(Integer.MAX_VALUE);
final Download theDownload = new Download();
theDownload.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if ("progress".equals(pcEvt.getPropertyName())) {
int progress = theDownload.getProgress();
atomLauncher.setProgress(progress);
}
}
});
theDownload.execute();
}
}
class AtomFrame extends JFrame {
// ********* should be private!
private JProgressBar progressBar;
private static final long serialVersionUID = 4010489530693307355L;
public static void main(String[] args) {
AtomFrame testFrame = new AtomFrame();
testFrame.start();
}
public void setProgress(int progress) {
progressBar.setValue(progress);
}
public AtomFrame() {
initializeComponents();
}
public void initializeComponents() {
this.setSize(400, 400);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Atom Launcher");
this.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
progressBar = new JProgressBar();
this.add(progressBar);
// this.pack();
}
public void start() {
this.setVisible(true);
}
public void close() {
this.dispose();
}
}
class Download extends SwingWorker<Void, Void> {
private static final long SLEEP_TIME = 300;
private Random random = new Random();
#Override
protected Void doInBackground() throws Exception {
int myProgress = 0;
while (myProgress < 100) {
myProgress += random.nextInt(10);
setProgress(myProgress);
try {
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {}
}
return null;
}
}
I already checked this duplicate question and other similar ones and it didn't help. I am trying to add an png to a button when it is clicked. The program is a variable sized tic-tac-toe game for school.
Right now I have:
private ImageIcon X_MARK = new ImageIcon("x.png");
private ImageIcon O_MARK = new ImageIcon("o.gif");
private JButton[][] cells;
...
cells = new JButton[size][size];
JPanel board = new JPanel(new GridLayout(size, size));
board.setBorder(new LineBorder(Color.BLACK, 1));
ButtonListener listener = new ButtonListener();
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++) {
cells[i][j] = new JButton();
cells[i][j].addActionListener(listener);
board.add(cells[i][j]);
}
JFrame ttt = new JFrame();
ttt.add(board);
ttt.setTitle("Show GUI Components");
ttt.setSize(60*size, 60*size);
ttt.setLocation(0, 0);
ttt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ttt.setVisible(true);
...
class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int i, j;
for (i = 0; i < size; i++)
for (j = 0; j < size; j++)
if (e.getSource() == cells[i][j]) {
if ((i + j) % 2 == 0) {
cells[i][j].setBackground(Color.GREEN);
cells[i][j].setIcon(X_MARK);
} else {
cells[i][j].setBackground(Color.CYAN);
cells[i][j].setIcon(O_MARK);
}
}
}
}
That is all the relevant code I think. I am using Eclipse and I have x.png and o.png in the src folder and the bin folder of the the project. I have also tried a couple of variants I have seen on SO and google searches like, new ImageIcon("C:/Users/BigBoy/workspace_1/EventDriven/src/x.png");, new ImageIcon("src/x.png");, and some other ones involving getClass().getResource among other things. I don't know what else to try. I know I've done this in the past and didn't have this much trouble.
I added .setBackground(Color.GREEN); just to make sure my clicks were registering properly and they are, the problem to me seems to be with the declaring/initializing of the ImageIcon.
NOTE: Right now my button listener just makes the checker board pattern, I will get to actually putting each player's mark after I figure out this icon problem.
You need to understand resources which is what you will want to use. They are located relative to the class files. If the images are with the class files, then
get your image as a resource
Create an ImageIcon from the Image.
i.e., something like:
package whateverpackeyouareusing;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
public class DefaultFoo {
public static void main(String[] args) throws IOException {
String resource = "x.png";
URL url = Class.class.getResource(resource);
BufferedImage img = ImageIO.read(url);
Icon icon = new ImageIcon(img);
JOptionPane.showMessageDialog(null, icon);
}
}
Edit: A better example per Andrew Thompson:
package some.package;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
public class PlayWithImages {
public static final String X_RESOURCE = "x.png";
private Icon xIcon;
public PlayWithImages() throws IOException {
URL xImgUrl = getClass().getResource(X_RESOURCE);
Image xImg = ImageIO.read(xImgUrl);
xIcon = new ImageIcon(xImg);
}
public Icon getXIcon() {
return xIcon;
}
public static void main(String[] args) {
try {
PlayWithImages playWithImages = new PlayWithImages();
Icon xIcon = playWithImages.getXIcon();
JOptionPane.showMessageDialog(null, xIcon);
} catch (IOException e) {
e.printStackTrace();
}
}
}
This question already has answers here:
How to set Icon to JFrame
(12 answers)
Closed 6 years ago.
I have a JFrame that displays a Java icon on the title bar (left corner).
I want to change that icon to my custom icon. How should I do it?
Create a new ImageIcon object like this:
ImageIcon img = new ImageIcon(pathToFileOnDisk);
Then set it to your JFrame with setIconImage():
myFrame.setIconImage(img.getImage());
Also checkout setIconImages() which takes a List instead.
Here is an Alternative that worked for me:
yourFrame.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource(Filepath)));
It's very similar to the accepted Answer.
JFrame.setIconImage(Image image) pretty standard.
Here is how I do it:
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import java.io.File;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
public class MainFrame implements ActionListener{
/**
*
*/
/**
* #param args
*/
public static void main(String[] args) {
String appdata = System.getenv("APPDATA");
String iconPath = appdata + "\\JAPP_icon.png";
File icon = new File(iconPath);
if(!icon.exists()){
FileDownloaderNEW fd = new FileDownloaderNEW();
fd.download("http://icons.iconarchive.com/icons/artua/mac/512/Setting-icon.png", iconPath, false, false);
}
JFrame frm = new JFrame("Test");
ImageIcon imgicon = new ImageIcon(iconPath);
JButton bttn = new JButton("Kill");
MainFrame frame = new MainFrame();
bttn.addActionListener(frame);
frm.add(bttn);
frm.setIconImage(imgicon.getImage());
frm.setSize(100, 100);
frm.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
and here is the downloader:
import java.awt.GridLayout;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
public class FileDownloaderNEW extends JFrame {
private static final long serialVersionUID = 1L;
public static void download(String a1, String a2, boolean showUI, boolean exit)
throws Exception
{
String site = a1;
String filename = a2;
JFrame frm = new JFrame("Download Progress");
JProgressBar current = new JProgressBar(0, 100);
JProgressBar DownloadProg = new JProgressBar(0, 100);
JLabel downloadSize = new JLabel();
current.setSize(50, 50);
current.setValue(43);
current.setStringPainted(true);
frm.add(downloadSize);
frm.add(current);
frm.add(DownloadProg);
frm.setVisible(showUI);
frm.setLayout(new GridLayout(1, 3, 5, 5));
frm.pack();
frm.setDefaultCloseOperation(3);
try
{
URL url = new URL(site);
HttpURLConnection connection =
(HttpURLConnection)url.openConnection();
int filesize = connection.getContentLength();
float totalDataRead = 0.0F;
BufferedInputStream in = new BufferedInputStream(connection.getInputStream());
FileOutputStream fos = new FileOutputStream(filename);
BufferedOutputStream bout = new BufferedOutputStream(fos, 1024);
byte[] data = new byte[1024];
int i = 0;
while ((i = in.read(data, 0, 1024)) >= 0)
{
totalDataRead += i;
float prog = 100.0F - totalDataRead * 100.0F / filesize;
DownloadProg.setValue((int)prog);
bout.write(data, 0, i);
float Percent = totalDataRead * 100.0F / filesize;
current.setValue((int)Percent);
double kbSize = filesize / 1000;
String unit = "kb";
double Size;
if (kbSize > 999.0D) {
Size = kbSize / 1000.0D;
unit = "mb";
} else {
Size = kbSize;
}
downloadSize.setText("Filesize: " + Double.toString(Size) + unit);
}
bout.close();
in.close();
System.out.println("Took " + System.nanoTime() / 1000000000L / 10000L + " seconds");
}
catch (Exception e)
{
JOptionPane.showConfirmDialog(
null, e.getMessage(), "Error",
-1);
} finally {
if(exit = true){
System.exit(128);
}
}
}
}
Just add the following code:
setIconImage(new ImageIcon(PathOfFile).getImage());
Unfortunately, the above solution did not work for Jython Fiji plugin. I had to use getProperty to construct the relative path dynamically.
Here's what worked for me:
import java.lang.System.getProperty;
import javax.swing.JFrame;
import javax.swing.ImageIcon;
frame = JFrame("Test")
icon = ImageIcon(getProperty('fiji.dir') + '/path/relative2Fiji/icon.png')
frame.setIconImage(icon.getImage());
frame.setVisible(True)
This did the trick in my case super or this referes to JFrame in my class
URL url = getClass().getResource("gfx/hi_20px.png");
ImageIcon imgicon = new ImageIcon(url);
super.setIconImage(imgicon.getImage());
Add the following code within the constructor like so:
public Calculator() {
initComponents();
//the code to be added this.setIconImage(newImageIcon(getClass().getResource("color.png")).getImage()); }
Change "color.png" to the file name of the picture you want to insert.
Drag and drop this picture onto the package (under Source Packages) of your project.
Run your project.