I'm starting to toy a little with the Leap Motion Controller and made a small GUI in Swing. That means it's just a Frame with a Label on it which should show a text of what the Leap Motion sees. Unfortunately my programm simply breaks down after two seconds. I have no Exceptions or something like that. Here's my code:
public class GUI extends JFrame{
private static final long serialVersionUID = 6411499808530678723L;
public JLabel label;
public GUI(){
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(300, 200);
this.label = new JLabel("Waiting for Gestures");
this.add(label);
setVisible(true);
}
public class LeapListener extends Listener{
JLabel label;
LeapListener(JLabel label){
this.label = label;
}
#Override
public void onInit(Controller controller){
}
#Override
public void onExit(Controller controller){
}
#Override
public void onConnect(Controller controller){
System.out.println("bin da");
controller.enableGesture(Gesture.Type.TYPE_CIRCLE);
controller.enableGesture(Gesture.Type.TYPE_KEY_TAP);
controller.enableGesture(Gesture.Type.TYPE_SCREEN_TAP);
controller.enableGesture(Gesture.Type.TYPE_SWIPE);
}
#Override
public void onDisconnect(Controller controller){
}
#Override
public void onFrame(Controller controller){
Frame frame = controller.frame();
GestureList glist = frame.gestures();
for (int i = 0; i < glist.count(); i++){
Gesture g = glist.get(i);
switch (g.type()){
case TYPE_CIRCLE:
CircleGesture circle = new CircleGesture(g);
this.label.setText("Mach mal nen Kreis!");
case TYPE_KEY_TAP:
KeyTapGesture key = new KeyTapGesture(g);
this.label.setText("Schreiben?");
case TYPE_SCREEN_TAP:
ScreenTapGesture screen = new ScreenTapGesture(g);
this.label.setText("Klicken?");
case TYPE_SWIPE:
SwipeGesture swipe = new SwipeGesture(g);
this.label.setText("Da wurde gewischt!");
default:
System.out.println("nothing!");
break;
}
}
}
}
public static void main(String[] args) {
GUI gui = new GUI();
LeapListener listener;
listener = gui.new LeapListener(gui.label);
Controller controller = new Controller();
controller.addListener(listener);
}
}
I have no idea what I've done wrong. The Windows-Error-Message says that the Java Platform SE binary is down (javaw.exe). Errormodule: Leap.dll
Is it a mistake that I've made or is my whole setup f#*ked up?
Ok, I found a solution by myself but unfortunately I can't explain it.
I have to create the Controller Object in the class declaration, not in the main-method. Then I have to add the listener to the controller in the constructor of my GUI, like that:
public class GUI extends JFrame{
private static final long serialVersionUID = 6411499808530678723L;
public JLabel label;
public Controller c = new Controller();
public LeapListener listener;
public GUI(){
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(300, 200);
this.label = new JLabel("Waiting for Gestures");
this.add(label);
listener = new LeapListener(this.label);
c.addListener(listener);
setVisible(true);
}
...
}
So, I'm happy that I got it to work but maybe somebody is interested in the problem and may find a reason for the error I've had.
Related
I've tried to apply the Observable/Observer pattern but there is something wrong with my code when I try to change a the textfield of a JTextPane.
I've got 3 classes, Play, Controller and SecondWindow here are a sample of their code.
public class Play() {
Controller c = new Controller();
SecondWindow sw = new SecondWindow();
c.addObserver(sw)
c.setText("blabla");
}
My class Controller:
public class Controller extends Observable(){
private String text ="";
private static Controller getInstance() {
if (instance == null) {
instance = new Controller();
}
return instance;
}
public void setText(String s) {
text = s;
setChanged();
notifyObservers();
}
}
and SecondWindow:
public class SecondWindow extends JFrame implements Observer{
private JPanel contentPane;
private Controller c;
private JTextPane txt = new JTextPane();
public SecondWindow () {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SecondWindow frame = new SecondWindow();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public SecondWindow() {
initComponents();
createEvents();
c = Controller.getInstance();
}
public void initComponents() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(1000, 0, 300,500);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
txt.setBounds(0, 0, 280, 460);
txt.enable(false);
contentPane.add(txt);
}
public void update(Observable arg0 , Object arg1){
// Things to change here
}
I can't manage to put the variable c in the textField (like a txt.setText(c.getText) instruction). I'm sure that it reads the method update, but I don't know how to make sure it works.
Hint: Per the Observerable API the notifyObservers method has an overload that accepts any object as a parameter:
public void notifyObservers(Object arg)
This can even be a String. And as per the Observer API, this object is then passed into the update method in the observer, and you can use it there.
void update(Observable o,
Object arg)
arg - an argument passed to the notifyObservers method.
Separate side issue here:
contentPane.setLayout(null);
For most Swing aficionados, seeing this is like hearing nails on a chalkboard -- it's painful. While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one. Instead you will want to study and learn the layout managers and then nest JPanels, each using its own layout manager to create pleasing and complex GUI's that look good on all OS's.
Side issue number two: your code is not Swing thread safe, since the Swing GUI could very well be notified by the observable off of the Swing event dispatch thread or EDT. While it is not likely to cause frequent or serious problems with this simple program, in general it would be better to use a SwingPropertyChangeSupport and PropertyChangeListeners rather than Observer / Observable if you can.
Next Side Issue
This:
public class Controller extends Observable(){
isn't compilable / kosher Java. Same for the duplicate parameter-less constructors for the SecondWindow class. Yes, we know what you're trying to do, but it's hard enough trying to understand someone else's code, you really don't want to make it harder by posting kind-of sort-of uncompilable code, trust me.
For example, something simple could be implemented in Swing using PropertyChangeListeners, like so:
import java.util.concurrent.TimeUnit;
public class Play2 {
public static void main(String[] args) {
Model2 model2 = new Model2();
View2 view2 = new View2();
new Controller2(model2, view2);
view2.show();
for (int i = 0; i < 10; i++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// one of the few times it's OK to ignore an exception
}
String text = String.format("Counter Value: %d", i);
model2.setText(text);
}
}
}
import java.beans.PropertyChangeListener;
import javax.swing.event.SwingPropertyChangeSupport;
public class Model2 {
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
public static final String TEXT = "text"; // name of our "bound" property
private String text = "";
public String getText() {
return text;
}
public void setText(String text) {
String oldValue = this.text;
String newValue = text;
this.text = text;
pcSupport.firePropertyChange(TEXT, oldValue, newValue);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
public void addPropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(name, listener);
}
public void removePropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(name, listener);
}
}
import javax.swing.*;
public class View2 {
private JPanel mainPanel = new JPanel();
private JTextField textField = new JTextField(10);
public View2() {
textField.setFocusable(false);
mainPanel.add(new JLabel("Text:"));
mainPanel.add(textField);
}
public JPanel getMainPanel() {
return mainPanel;
}
public void setText(String text) {
textField.setText(text);
}
public void show() {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("View");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(getMainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
public class Controller2 {
private Model2 model2;
private View2 view2;
public Controller2(Model2 model2, View2 view2) {
this.model2 = model2;
this.view2 = view2;
model2.addPropertyChangeListener(Model2.TEXT, new ModelListener());
}
private class ModelListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent pcEvt) {
view2.setText((String) pcEvt.getNewValue());
}
}
}
I'm learning to design a class diagram for java and this is my first attempt. Could you please tell me if it's okay.
Here's the source code
public class DiceRoll1 extends JFrame implements ActionListener {
private JTextField txtNotation;
private JButton btRoll, btShuffle;
private List<Integer> dealtCard;
private History history;
public DiceRoll1() {
initComponents();
dealtCard = new ArrayList<>();
history = new History();
}
public void initComponents() {
//designing the userform
setSize(400, 500);
setLayout(new FlowLayout());
setTitle("Dice Roll");
txtNotation = new JTextField("2d6");
btRoll = new JButton("Roll");
btShuffle = new JButton("Shuffle");
txtNotation.setColumns(20);
getContentPane().add(txtNotation);
getContentPane().add(btRoll);
getContentPane().add(btShuffle);
btRoll.addActionListener(this);
btShuffle.addActionListener(this);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new DiceRoll().setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
JButton source = (JButton) e.getSource();
if (source.equals(btRoll)) {
} else if (source.equals(btShuffle)) {
}
}
public void displayOutput(String message) {
System.out.println(message);
}
}
Here's the diagram that i have drawn using Visio professional:
I think that your diagram isn't too bad but I noticed some things.
the names of your attributes in the code and the diagram are not consistent
You don't need to add Java built-in classes except you extend or implement them or you're told to do so because they unnecessarily inflate your diagram
You should draw an inheritance connection between JFrame and your class
You should draw a realization connection between ActionListeners and your class
Connection types of an UML-Class-Diagram
I'm currently working on a project that involves using the Model-View-Controller architecture, in the project I have to implement freehand drawing inside of a JPanel, however the panel.paintComponent(g) method doesn't seem to work.
In my view package I create the GUI and give each object a getter, my controller class creates a GUI and uses these getters to instantiate the JPanels, JButtons etc. The Drawing model is passed the JPanel I want to draw on, as seen below.
public class Editor extends JPanel implements MouseListener, MouseMotionListener {
private int index = 0;
private Point[] arr = new Point[100000];
private JPanel xPanel = new JPanel();
Updater upDate = new Updater();
public void getPanel(JPanel dPanel)
{
xPanel = dPanel;
xPanel.addMouseListener(this);
xPanel.addMouseMotionListener(this);
xPanel.setBackground(Color.white);
}
public void paintComponent(Graphics g)
{
System.out.println("Got to this point");
xPanel.paintComponents(g);
for(int i = 0; i < index - 1; i++)
{
System.out.println("And here 2");
g.drawLine(arr[i].x, arr[i].y, arr[i+1].x, arr[i+1].y);
System.out.println("And here 3");
}
}
#Override
public void mousePressed(java.awt.event.MouseEvent e) {
arr[index] = new Point(e.getX(), e.getY());
index++;
System.out.println(index);
upDate.update(xPanel);
}
#Override
public void mouseDragged(java.awt.event.MouseEvent e) {
arr[index] = new Point(e.getX(), e.getY());
index++;
System.out.println(index);
upDate.update(xPanel);
}
My Controller class looks like this.
private GUI view;
private JButton buttonLoad;
private JButton buttonZoom;
private JButton buttonDrag;
private JButton buttonSave;
private JButton buttonRotate;
private JButton buttonDraw;
private JMenuBar menuB;
private JPanel dPanel;
private MouseListener e;
Graphics g;
public Controller(GUI gui){
this.view = gui;
menuB = view.getMenu();
buttonLoad = view.getLoad();
buttonZoom = view.getZoom();
buttonRotate = view.getRotate();
buttonSave = view.getSave();
buttonDrag = view.getDrag();
buttonDraw = view.getDraw();
dPanel = view.getModel();
g = dPanel.getGraphics();
FunctionListener x = new FunctionListener();
MenuBarListener y = new MenuBarListener();
buttonLoad.addActionListener(x);
buttonZoom.addActionListener(x);
buttonRotate.addActionListener(x);
buttonSave.addActionListener(x);
buttonDrag.addActionListener(x);
buttonDraw.addActionListener(x);
//menuB.addMenuListener(y);
}
class FunctionListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource().equals(buttonZoom)){
Editor editor = new Editor();
editor.getPanel(dPanel);
editor.paintComponent(g);
}
It's worth noting that dPanel = view.getModel(); is a getter for a JPanel called Model in my GUI class. Everything seems to be working, the index of points is being returned properly yet there is no drawing, after running some simple System.out.println tests, I know that the code isn't entering the for loop in the Editor class.
Thanks for any help!
I'm programming in Java, trying to use a cardholder in order to switch between 2 JPanels which are each an extension of their own class. I think I understand the basic concepts but I am having errors in my current revision, when calling the classes. I'm getting a null pointer exception and I think it's a structural problem but I'm not sure how or why.
The main method points to this class
public class Skeleton implements ActionListener{
JPanel cardHolder;
CardLayout cards;
String cardA = "A";
String cardB = "B";
JPanel Jboard;
JPanel Jmenu;
JFrame frame2;
Board board;
Menu menu;
boolean menuSet;
boolean boardSet;
Timer timer;
public class Switcher implements ActionListener{
String card;
Switcher(String card){
this.card = card;
}
#Override
public void actionPerformed(ActionEvent e) {
cards.show(cardHolder, card);
}
}
public Skeleton(JFrame frame){
JPanel menu = new Menu();
JPanel board = new Board();
JFrame frame2 = frame;
timer = new Timer(5, this);
timer.start();
cardHolder = new JPanel();
cards = new CardLayout();
cardHolder.setLayout(cards);
cardHolder.add(menu, cardA);
cardHolder.add(board, cardB);
frame2.add(cardHolder);
frame2.revalidate();
frame2.setVisible(true);
}
public JFrame getSkeleton(){
return frame2;
}
public JPanel getCardHolder(){
return cardHolder;
}
public void checkStatus(){
if (menuSet == true){
new Switcher(cardB);
boardSet = false;
}
if (boardSet == true){
new Switcher(cardA);
menuSet = false;
}
}
#Override
public void actionPerformed(ActionEvent e) {
menuSet = menu.getMenuset();
boardSet = board.getBoardset();
checkStatus();
}
}
This is the board class, one of the JPanels I'm trying to switch between
public class Board extends JPanel{
boolean boardset;
Menu menu = new Menu();
public Board(){
setBackground(Color.WHITE);
}
public JPanel getPanel(){
return this;
}
public void setBoardset(boolean x){
boardset = x;
}
public boolean getBoardset(){
return boardset;
}
}
Here is the other JPanel class, which contains a button used to switch to the other JPanel class. This is also the original starting JPanel used.
public class Menu extends JPanel implements ActionListener{
boolean menuset;
public Menu(){
setBackground(Color.BLACK);
JButton button = new JButton("hello");
button.addActionListener(this);
this.add(button);
}
public JPanel getPanel(){
return this;
}
#Override
public void actionPerformed(ActionEvent e) {
menuset = true;
}
public void setMenuset(boolean x){
menuset = x;
}
public boolean getMenuset(){
return menuset;
}
}
Like I said, I'm getting a null pointer exception. It is occuring on this line of the Skeleton() class
menuSet = menu.getMenuset();
The line above is right after the actionPerformed event above (from the timer), and I have tested the timer a little, it works doing basic print statements but whenever I try to use the 'menu' or 'board' instance inside the actionPerformed, I get this null pointer exception.
I would appreciate any advice. I get the idea that the way I'm doing this may be a little convoluted. If anyone has any suggestions on a better way to do this it would also be helpful. My main goal is to be able to call 2 separate classes from one main class containing a cardholder. That way I can separate the code in order to keep everything isolated and in order.
Your Skeleton class has a "menu" member but it isn't set anywhere that I can see. The constructor declares its own "menu" local variable, which is local to the constructor and hides the member. Setting "menu" inside the constructor won't set the member. I don't see anywhere else where the "menu" member is set, unless I've missed something or unless another class in the same package is setting it.
I am using a gui with JTextFields to collect some information and then a JButton that takes that infomration and writes it to a file, sets the gui visibility to false, and then uses Runnable to create an instance of another JFrame from a different class to display a slideshow.
I would like to access some of the information for the JTextFields from the new JFrame slideshow. I have tried creating an object of the previous class with accessor methods, but the values keep coming back null (I know that I have done this correctly).
I'm worried that when the accessor methods go to check what the variables equal the JTextFields appear null to the new JFrame.
Below is the sscce that shows this problem.
package accessmain;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class AccessMain extends JFrame implements ActionListener
{
private static final int FRAMEWIDTH = 800;
private static final int FRAMEHEIGHT = 300;
private JPanel mainPanel;
private PrintWriter outputStream = null;
private JTextField subjectNumberText;
private String subjectNumberString;
public static void main(String[] args)
{
AccessMain gui = new AccessMain();
gui.setVisible(true);
}
public AccessMain()
{
super("Self Paced Slideshow");
setSize(FRAMEWIDTH, FRAMEHEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
//Begin Main Content Panel
mainPanel = new JPanel();
mainPanel.setBorder(new EmptyBorder(0,10,0,10));
mainPanel.setLayout(new GridLayout(7, 2));
mainPanel.setBackground(Color.WHITE);
add(mainPanel, BorderLayout.CENTER);
mainPanel.add(new JLabel("Subject Number: "));
subjectNumberText = new JTextField(30);
mainPanel.add(subjectNumberText);
mainPanel.add(new JLabel(""));
JButton launch = new JButton("Begin Slideshow");
launch.addActionListener(this);
mainPanel.add(launch);
//End Main Content Panel
}
#Override
public void actionPerformed(ActionEvent e)
{
String actionCommand = e.getActionCommand();
if(actionCommand.equals("Begin Slideshow"))
{
subjectNumberString = subjectNumberText.getText();
if(!(subjectNumberString.equals("")))
{
System.out.println(getSubjectNumber());
this.setVisible(false);
writeFile();
outputStream.println("Subject Number:\t" + subjectNumberString);
outputStream.close();
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
AccessClass testClass = new AccessClass();
testClass.setVisible(true);
}
});
}
else
{
//Add warning dialogue here later
}
}
}
private void writeFile()
{
try
{
outputStream = new PrintWriter(new FileOutputStream(subjectNumberString + ".txt", false));
}
catch(FileNotFoundException e)
{
System.out.println("Cannot find file " + subjectNumberString + ".txt or it could not be opened.");
System.exit(0);
}
}
public String getSubjectNumber()
{
return subjectNumberString;
}
}
And then creating a barebones class to show the loss of data:
package accessmain;
import javax.swing.*;
import java.awt.*;
public class AccessClass extends JFrame
{
AccessMain experiment = new AccessMain();
String subjectNumber = experiment.getSubjectNumber();
public AccessClass()
{
System.out.println(subjectNumber);
}
}
Hardcoding the accessor method with "test" like this:
public String getSubjectNumber()
{
return "test";
}
Running this method as below in the new JFrame:
SelfPaceMain experiment = new SelfPaceMain();
private String subjectNumber = experiment.getSubjectNumber();
System.out.println(subjectNumber);
Does cause the system to print "test". So the accessor methods seem to be working. However, trying to access the values from the JTextFields doesn't seem to work.
I would read the information from the file I create, but without being able to pass the subjectNumber (which is used as the name of the file), I can't tell the new class what file to open.
Is there a good way to pass data from JTextFields to other classes?
pass the argument 'AccessMain' or 'JTextField' to the second class:
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
AccessClass testClass = new AccessClass(AccessMain.this); //fixed this
testClass.setVisible(true);
}
});
Then reading the value of 'subjectNumber'(JTextField value) from the 'AccessMain' or 'JTextField' in the second class:
public class AccessClass extends JFrame
{
final AccessMain experiment;
public AccessClass(AccessMain experiment)
{
this.experiment = experiment;
}
public String getSubjectNumber(){
return experiment.getSubjectNumber();
}
}
Also, you should try Observer pattern.
A simple demo of Observalbe and Observer
Observable and Observer Objects