How to draw on jPanel with JOgl - netbeans

I use JOGL in Netbeans 8.0.2. I want to draw the classic colored triangle on a panel and also to select number of sides of the geometrical figure (4, 5 sides) using the Netbeans palette controls but I have no idea how.The panel is on the frame. So far my code is :
Class PanelGL:
package panelgl;
import com.jogamp.opengl.*;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.awt.GLJPanel;
import java.awt.Dimension;
import javax.swing.JFrame;
public class PanelGL implements GLEventListener{
public static void main(String[] args) {
final GLProfile profile = GLProfile.get( GLProfile.GL2 );
GLCapabilities capabilities = new GLCapabilities(profile);
final GLJPanel glpanel = new GLJPanel( capabilities );
PanelGL triangle = new PanelGL();
glpanel.addGLEventListener( triangle );
glpanel.setSize( 400, 400 );
final GLFrame frame = new GLFrame ("Colored Triangle");
frame.getContentPane().add( glpanel );
frame.setSize( frame.getContentPane().getPreferredSize());
frame.setVisible( true );
}
#Override
public void init(GLAutoDrawable glad) { }
#Override
public void dispose(GLAutoDrawable glad) { }
#Override
public void display(GLAutoDrawable glad) {
final GL2 gl = glad.getGL().getGL2();
gl.glBegin( GL2.GL_TRIANGLES );
gl.glColor3f( 1.0f, 0.0f, 0.0f ); // Red
gl.glVertex3f( 0.5f,0.7f,0.0f ); // Top
gl.glColor3f( 0.0f,1.0f,0.0f ); // green
gl.glVertex3f( -0.2f,-0.50f,0.0f ); // Bottom Left
gl.glColor3f( 0.0f,0.0f,1.0f ); // blue
gl.glVertex3f( 0.5f,-0.5f,0.0f ); // Bottom Right
gl.glEnd();
}
#Override
public void reshape(GLAutoDrawable glad, int i, int i1, int i2, int i3) { }
}
Class GLFrame
public class GLFrame extends javax.swing.JFrame {
public GLFrame(String title) {
this.setTitle(title);
initComponents();
}
private javax.swing.JPanel glPanel;
}
glPanel is add via palette.
I want that the drawing to be on this specifically panel (glPanel).

Create a class that extends GLJPanel instead of GLEventListener. You would still use the GLEventListener internally. After you have compiled the class you can right click it in the Projects window for the pop-up menu to select Tools -> Add To Palette ... to add it to the palette. To Create a property that will be editable just use the normal bean pattern with getter and setter or use Alt-Insert and then select Add Property to add the variable and getter and setter.
eg..
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLJPanel;
import java.awt.Dimension;
public class MyJOGLFigure extends GLJPanel {
public MyJOGLFigure() {
this.setPreferredSize(new Dimension(100,100));
final GLProfile profile = GLProfile.get(GLProfile.GL2);
GLCapabilities capabilities = new GLCapabilities(profile);
this.addGLEventListener(new GLEventListener() {
#Override
public void init(GLAutoDrawable glad) {
}
#Override
public void dispose(GLAutoDrawable glad) {
}
#Override
public void display(GLAutoDrawable glad) {
System.out.println("numberOfSides = " + numberOfSides);
final GL2 gl = glad.getGL().getGL2();
gl.glBegin(GL2.GL_TRIANGLES);
gl.glColor3f(1.0f, 0.0f, 0.0f); // Red
gl.glVertex3f(0.5f, 0.7f, 0.0f); // Top
gl.glColor3f(0.0f, 1.0f, 0.0f); // green
gl.glVertex3f(-0.2f, -0.50f, 0.0f); // Bottom Left
gl.glColor3f(0.0f, 0.0f, 1.0f); // blue
gl.glVertex3f(0.5f, -0.5f, 0.0f); // Bottom Right
gl.glEnd();
}
#Override
public void reshape(GLAutoDrawable glad, int i, int i1, int i2, int i3) {
}
});
}
// Example editable property.
private int numberOfSides = 3;
/**
* Get the value of numberOfSides
*
* #return the value of numberOfSides
*/
public int getNumberOfSides() {
return numberOfSides;
}
/**
* Set the value of numberOfSides
*
* #param numberOfSides new value of numberOfSides
*/
public void setNumberOfSides(int numberOfSides) {
this.numberOfSides = numberOfSides;
}
}
After you have dragged the MyJoglFigure from the palette to the JFrame design, you can find and edit the numberOfSides property. NOTE that I only print it, i didn't actually use it to change the drawing. ( exercise for the reader ? )

Related

Implement undo/redo button in JavaFX [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 months ago.
Improve this question
Ive been scrolling and scrolling and i dont seem to find any solution. I am making a simple java fx program where i draw different shapes. The problem is that i dont know how to implement an undo button. I have found that you can use stacks, command pattern, arraydeque and so on... But i cant fix it..
Here is some of the code.
public class shapeModel {
//private final List<Shape> undoHistory = new ArrayList<>();
//private final Deque<Deque<Shape>> redoHistory;
private final ObservableList<Shape> shapeList;
private final ObjectProperty<Color> colorPickerSelect;
private final int historyIndex = -1;
private ShapeType currentShape;
public shapeModel() {
//this.redoHistory = new ArrayDeque<>();
this.colorPickerSelect = new SimpleObjectProperty<>(Color.GREEN);
this.shapeList = FXCollections.observableArrayList(shape -> new Observable[]{
shape.colorProperty()
});
}
public ShapeType getCurrentShape() {
return currentShape;
}
public void setCurrentShape(ShapeType currentShape) {
this.currentShape = currentShape;
}
public void addShapes(Shape shape) {
if (!(shape == null))
this.shapeList.add(shape);
}
public Color getColorPickerSelect() {
return colorPickerSelect.get();
}
public ObjectProperty<Color> colorPickerSelectProperty() {
return colorPickerSelect;
}
public ObservableList<Shape> getShapeObservableList() {
return shapeList;
}
public void undo() {
}
}
Controller class:
public class HelloController {
public Button eraserButton;
public Button undoButton;
public BorderPane scenePane;
public ColorPicker myColorPicker;
public ChoiceBox<String> myChoiceBox;
public GraphicsContext context;
public Canvas canvas;
public shapeModel model;
public void initialize() {
context = canvas.getGraphicsContext2D();
model.getShapeObservableList().addListener((ListChangeListener<Shape>) e -> listChanged());
myColorPicker.valueProperty().bindBidirectional(model.colorPickerSelectProperty());
}
public HelloController() {
this.model = new shapeModel();
}
//
// private int count = 0;
//
// private final Shape[] shapes = new Shape[30];
public void canvasClicked(MouseEvent mouseEvent) {
Shape shape = Shape.creatingShapes(model.getCurrentShape(),mouseEvent.getX(),mouseEvent.getY(),50,50,myColorPicker.getValue());
model.addShapes(shape);
// redraw();
// shapes[count] = shape;
// count++;
// paintCanvas();
}
public void listChanged() {
var context = canvas.getGraphicsContext2D();
model.getShapeObservableList().forEach(s -> s.draw(context));
}
public void undoClicked() {
}
// public void redo() {
//
// if(historyIndex < model.getShapeObservableList().size()-1) {
// historyIndex++;
// model.getShapeObservableList(),(historyIndex).
// }
//
// }
public void handleClick() {
FileChooser chooser = new FileChooser();
File file = chooser.showSaveDialog(scenePane.getScene().getWindow());
}
public void onCircleClicked(ActionEvent e) {
model.setCurrentShape(ShapeType.CIRCLE);
}
public void onRectangleClicked(ActionEvent e) {
model.setCurrentShape(ShapeType.RECTANGLE);
}
public void exitAction(ActionEvent actionEvent) {
Platform.exit();
}
public void eraser() {
context.setFill(Color.WHITE);
context.fillRect(0,0,canvas.getWidth(), canvas.getHeight());
// context.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
}
}
Maybe this can help. This is my first time attempting something like this. The experts may have a better, more efficient way of doing this.
My idea was to keep up with a List of WritableImages as you draw. Use that list to go forward and backward through history.
Main
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.WritableImage;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundImage;
import javafx.scene.layout.BackgroundPosition;
import javafx.scene.layout.BackgroundRepeat;
import javafx.scene.layout.BackgroundSize;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
/**
* Code from: #web http://java-buddy.blogspot.com/
*/
public class App extends Application {
Canvas canvas = new Canvas(400, 400);
StackPane spCanvasHolder = new StackPane(canvas);
List<WritableImage> history = new ArrayList();
AtomicInteger currentlyDisplaying = new AtomicInteger();
#Override
public void start(Stage primaryStage) {
final GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
initDraw(graphicsContext);
canvas.addEventHandler(MouseEvent.MOUSE_PRESSED, (MouseEvent event) ->
{
graphicsContext.beginPath();
graphicsContext.moveTo(event.getX(), event.getY());
graphicsContext.stroke();
history.add(spCanvasHolder.snapshot(new SnapshotParameters(), null));
System.out.println("Current Display: " + currentlyDisplaying.incrementAndGet());
});
canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, (MouseEvent event) ->
{
graphicsContext.lineTo(event.getX(), event.getY());
graphicsContext.stroke();
history.add(spCanvasHolder.snapshot(new SnapshotParameters(), null));
System.out.println("Current Display: " + currentlyDisplaying.incrementAndGet());
});
canvas.addEventHandler(MouseEvent.MOUSE_RELEASED, (MouseEvent event) ->
{
System.out.println("History size: " + history.size());
});
Button btnForwardHistory = new Button(">");
btnForwardHistory.setOnAction((t) ->
{
if(currentlyDisplaying.get() < history.size())
{
File file = new File("CanvasTemp.png");
try
{
canvas.getGraphicsContext2D().clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
ImageIO.write(SwingFXUtils.fromFXImage(history.get(currentlyDisplaying.incrementAndGet()), null), "png", file);
BackgroundImage bI = new BackgroundImage(new Image(new FileInputStream(file)), BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT, BackgroundSize.DEFAULT);
spCanvasHolder.setBackground(new Background(bI));
}
catch (Exception s) {
System.out.println(s.toString());
}
}
});
Button btnBackwardHistory = new Button("<");
btnBackwardHistory.setOnAction((t) ->
{
System.out.println("Current Display: " + currentlyDisplaying.get());
if(currentlyDisplaying.get() > 0)
{
File file = new File("CanvasTemp.png");
try
{
canvas.getGraphicsContext2D().clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
ImageIO.write(SwingFXUtils.fromFXImage(history.get(currentlyDisplaying.decrementAndGet()), null), "png", file);
BackgroundImage bI = new BackgroundImage(new Image(new FileInputStream(file)), BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT, BackgroundSize.DEFAULT);
spCanvasHolder.setBackground(new Background(bI));
}
catch (Exception s) {
System.out.println(s.toString());
}
}
});
VBox vbHistoryControls = new VBox(btnBackwardHistory, btnForwardHistory);
StackPane root = new StackPane();
root.getChildren().add(new HBox(vbHistoryControls, spCanvasHolder));
Scene scene = new Scene(root);
primaryStage.setTitle("java-buddy.blogspot.com");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private void initDraw(GraphicsContext gc){
double canvasWidth = gc.getCanvas().getWidth();
double canvasHeight = gc.getCanvas().getHeight();
gc.setFill(Color.LIGHTGRAY);
gc.setStroke(Color.BLACK);
gc.setLineWidth(5);
gc.fill();
gc.strokeRect(
0, //x of the upper left corner
0, //y of the upper left corner
canvasWidth, //width of the rectangle
canvasHeight); //height of the rectangle
gc.setFill(Color.RED);
gc.setStroke(Color.BLUE);
gc.setLineWidth(1);
}
}
module-info
module com.mycompany.javafxsimpletest {
requires javafx.controls;
requires javafx.swing;
exports com.mycompany.javafxsimpletest;
}
Output
I would not use this code in a production app, but maybe the ideas can get you in the right direction.
This example is based on the UndoFX framework:
https://github.com/FXMisc/UndoFX
I offer up the example without a lot of explanation. You could study and learn from it or ignore it. It isn't going to do exactly what you want, but there might be some useful ideas from it for you.
The example:
Uses the scene graph instead of a Canvas.
Only adds shapes to a pane.
Provides the ability to remove the added shapes and add them back again.
The example is probably overcomplicated for the limited functionality it provides but might be structured in such a way that it is more easily adaptable to adding additional functionality.
The example does not demonstrate manipulating shapes (such as selecting them, changing their border and fill colors, changing their sizes, etc) and undoing or redoing such changes. But if you wanted to extend functionality for that, you could use the app as a basis and look into the UndoFX demo app which shows how to apply undo and redo to multiple properties on a shape. Depending on the functionality added, this could be quite a difficult task as generic undo/redo across a wide range of functionality is inherently difficult (IMO).
com/example/shapechanger/ShapeChangerApp.java
package com.example.shapechanger;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;
import org.fxmisc.undo.UndoManager;
import org.fxmisc.undo.UndoManagerFactory;
import org.reactfx.EventSource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class ShapeChangerApp extends Application {
#Override
public void start(Stage stage) {
Model model = new Model();
EventSource<ShapeChange> changes = new EventSource<>();
UndoManager<ShapeChange> undoManager = new UndoProvider(changes).getUndoManager();
Ribbon ribbon = new Ribbon(model, undoManager);
DrawingPane drawingPane = new DrawingPane(model, changes);
ScrollPane scrollPane = new ScrollPane(drawingPane);
scrollPane.setPrefSize(300, 300);
VBox layout = new VBox(ribbon, scrollPane);
VBox.setVgrow(scrollPane, Priority.ALWAYS);
Scene scene = new Scene(layout);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
class DrawingPane extends Pane {
private static final double DRAWING_PANE_SIZE = 1_000;
private final Model model;
private final EventSource<ShapeChange> changes;
private final ShapeFactory shapeFactory = new ShapeFactory();
public DrawingPane(Model model, EventSource<ShapeChange> changes) {
this.model = model;
this.changes = changes;
setOnMouseClicked(e -> addShape(e.getX(), e.getY()));
setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
setPrefSize(DRAWING_PANE_SIZE, DRAWING_PANE_SIZE);
setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
}
private void addShape(double x, double y) {
DrawableShape drawableShape = model.selectedShapeProperty().get();
Shape shape = shapeFactory.create(
drawableShape, x, y
);
ShapeChange shapeChange = new ShapeChange(
changes, this, shape, true
);
shapeChange.apply();
}
}
class Model {
private final ObjectProperty<DrawableShape> selectedShape = new SimpleObjectProperty<>();
public ObjectProperty<DrawableShape> selectedShapeProperty() {
return selectedShape;
}
}
class Ribbon extends ToolBar {
public Ribbon(Model model, UndoManager<ShapeChange> undoManager) {
UndoControls undoControls = new UndoControls(undoManager);
ShapeSelector shapeSelector = new ShapeSelector();
model.selectedShapeProperty().bindBidirectional(
shapeSelector.selectedShapeProperty()
);
getItems().addAll(undoControls.getControls());
getItems().add(createSpacer());
getItems().addAll(shapeSelector.getControls());
}
private Node createSpacer() {
Pane spacer = new Pane();
spacer.setPrefWidth(10);
return spacer;
}
}
class UndoProvider {
private final UndoManager<ShapeChange> undoManager;
public UndoProvider(EventSource<ShapeChange> changes) {
undoManager = UndoManagerFactory.unlimitedHistorySingleChangeUM(
changes,
ShapeChange::invert,
ShapeChange::apply
);
}
public UndoManager<ShapeChange> getUndoManager() {
return undoManager;
}
}
class ShapeChange {
private final EventSource<ShapeChange> changes;
private final DrawingPane drawingPane;
private final Shape shape;
private final boolean adding;
public ShapeChange(EventSource<ShapeChange> changes, DrawingPane drawingPane, Shape shape, boolean adding) {
this.changes = changes;
this.drawingPane = drawingPane;
this.shape = shape;
this.adding = adding;
}
public void apply() {
if (adding) {
drawingPane.getChildren().add(shape);
} else {
drawingPane.getChildren().remove(shape);
}
changes.push(this);
}
public ShapeChange invert() {
return new ShapeChange(
this.changes,
this.drawingPane,
this.shape,
!adding
);
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ShapeChange that = (ShapeChange) o;
return adding == that.adding && Objects.equals(changes, that.changes) && Objects.equals(drawingPane, that.drawingPane) && Objects.equals(shape, that.shape);
}
#Override
public int hashCode() {
return Objects.hash(changes, drawingPane, shape, adding);
}
}
enum DrawableShape {
SQUARE, CIRCLE
}
class UndoControls {
private final Button undo = new Button("<");
private final Button redo = new Button(">");
public UndoControls(UndoManager<ShapeChange> undoManager) {
undo.disableProperty().bind(undoManager.undoAvailableProperty().map(x -> !x));
redo.disableProperty().bind(undoManager.redoAvailableProperty().map(x -> !x));
undo.setOnAction(evt -> undoManager.undo());
redo.setOnAction(evt -> undoManager.redo());
}
public List<Node> getControls() {
return List.of(undo, redo);
}
}
class ShapeSelector {
private final ObjectProperty<DrawableShape> selectedShape = new SimpleObjectProperty<>(DrawableShape.SQUARE);
private final RadioButton squareSelector = looksLikeToggleButton(new RadioButton());
private final RadioButton circleSelector = looksLikeToggleButton(new RadioButton());
public ShapeSelector() {
ShapeFactory shapeFactory = new ShapeFactory();
Rectangle square = shapeFactory.createSquare(0, 0, Color.LIGHTGRAY);
Circle circle = shapeFactory.createCircle(0, 0, Color.LIGHTGRAY);
ToggleGroup toggleGroup = new ToggleGroup();
squareSelector.setGraphic(square);
squareSelector.setToggleGroup(toggleGroup);
squareSelector.setSelected(true);
circleSelector.setGraphic(circle);
circleSelector.setToggleGroup(toggleGroup);
Map<Toggle,DrawableShape> shapeMap = Map.of(
squareSelector, DrawableShape.SQUARE,
circleSelector, DrawableShape.CIRCLE
);
toggleGroup.selectedToggleProperty().addListener((observable, oldValue, newValue) ->
selectedShape.set(
shapeMap.get(newValue)
)
);
}
public ObjectProperty<DrawableShape> selectedShapeProperty() {
return selectedShape;
}
public List<Node> getControls() {
return List.of(squareSelector, circleSelector);
}
private RadioButton looksLikeToggleButton(RadioButton radioButton) {
radioButton.getStyleClass().remove("radio-button");
radioButton.getStyleClass().add("toggle-button");
return radioButton;
}
}
class ShapeFactory {
private static final double BASE_SIZE = 20;
private static final double STROKE_WIDTH = 3;
private static final List<Color> palette = List.of(
Color.LIGHTBLUE,
Color.LIGHTGREEN,
Color.LIGHTCORAL,
Color.LIGHTGOLDENRODYELLOW,
Color.LIGHTPINK,
Color.LIGHTSALMON,
Color.LIGHTSEAGREEN,
Color.LIGHTYELLOW
);
private int colorIdx = 0;
public Rectangle createSquare(double x, double y, Color color) {
Rectangle square = new Rectangle(BASE_SIZE, BASE_SIZE);
square.setFill(color);
square.setStroke(color.darker());
square.setStrokeWidth(STROKE_WIDTH);
square.relocate(x, y);
return square;
}
public Circle createCircle(double x, double y, Color color) {
Circle circle = new Circle(BASE_SIZE / 2);
circle.setFill(color);
circle.setStroke(color.darker());
circle.setStrokeWidth(STROKE_WIDTH);
circle.setCenterX(x);
circle.setCenterY(y);
return circle;
}
public Shape create(DrawableShape drawableShape, double x, double y) {
return switch (drawableShape) {
case SQUARE -> createSquare(x, y, nextColor());
case CIRCLE -> createCircle(x, y, nextColor());
};
}
private Color nextColor() {
Color chosenColor = palette.get(colorIdx);
colorIdx = (colorIdx + 1) % palette.size();
return chosenColor;
}
}
module-info.java
module com.example.shapechanger {
requires javafx.controls;
requires org.fxmisc.undo;
requires reactfx;
exports com.example.shapechanger;
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>ShapeChanger</artifactId>
<version>1.0-SNAPSHOT</version>
<name>ShapeChanger</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>19</version>
</dependency>
<dependency>
<groupId>org.fxmisc.undo</groupId>
<artifactId>undofx</artifactId>
<version>2.1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>19</source>
<target>19</target>
<compilerArgs>--enable-preview</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>

JButton accessible for several Panels

I'm new at Java Programming and have "beginner Question".
I already tried to find wether someone already had the same problem, but I couldn't find any posts which were on my low level.
My Problem:
I have 2 JPanels in one of them, (let's call it Panel1) I implements a JTextField (field1) and a JButton (button1). on Panel2 I want to draw something, depending on what the using tipped in the first JTextField.
My Problem is I want Panel2 to "see" that button1 (in Panel1) , which I don't manage to do.
Can anyone give me a hint, a Youtube Video or something like that, where I can see a nice example where someone handles such a Problem?
Greetings Ventura
P.S I had an idea to pass values to Panel2 where it should draw those things I want, here my code up so far (I hope I post it correctly): Here Panel1:
public class Panel1 extends JPanel
{
public JButton button = new JButton("OK");
public JTextField field1 = new JTextField(5);
public String name;int b;
public Panel1()
{
setBackground(Color.WHITE);
add(field1);
add(button);
ButtonListener listener = new ButtonListener(field1);
button.addActionListener(listener);
}
public Dimension getPreferredSize()
{
return new Dimension(400,400);
}
}
Here the ButtonListener :
class ButtonListener implements ActionListener
{
Graphics g;
//Graphics2D g2 = (Graphics2D) g;
public Panel2 pan2 = new Panel2();
public String name;
public JTextField field1 = new JTextField();
int b;
public ButtonListener(JTextField field1)
{this.field1 = field1;}
public void actionPerformed(ActionEvent e)
{
String op = e.getActionCommand();
if(op.equals("OK"))
{
name = field1.getText();
try
{
b = Integer.parseInt(name);
JOptionPane.showMessageDialog(null,"Ihre Zahl = "+b);
pan2.setvalue(b,g);
}
catch(NumberFormatException ex) {JOptionPane.showMessageDialog(null,"Please enter real numbers!");}
}
}
}
And finally Panel2 where I'd like to draw things based on the Input given in Panel1 (for example: I type in 10 and he draws me a Rectangle with width 10 or something like that)
public class Panel2 extends JPanel
{
Graphics g;
Graphics2D g2 = (Graphics2D) g;
public int b;
public Panel2()
{
setBackground(Color.YELLOW);
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
super.paintComponent(g);
g2.setColor(Color.RED);
g2.fillRect(200, 200, 50, 50);
Paint2(g);
}
public void Paint2(Graphics g)
{
this.g = g;
Graphics2D g2 = (Graphics2D) g;
//super.paintComponent(g);
System.out.println("TEST2");
g2.setColor(Color.BLUE);
//System.out.println("TEST3");
g2.fillRect(10 , 10, 40, 40);
}
public void setvalue(int b, Graphics g)
{
this.b = b;
this.g = g;
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.CYAN);
g2.fillRect(0, 0, 40, 40);
System.out.println("B ist gleich = "+b);
//Paint2(g2);
}
public Dimension getPreferredSize()
{
return new Dimension(400,400);
}
I'm sorry if it is a little cumbersome to read.
My basic Problem I get in this code is the NullpointerException in Panel2 when I want to call the Method
setvalue(int b, Graphics g)
g2.setColor(Color.Cyan)
Greetings Patrick
I did a redesign to most of Panel1 and a little bit to Panel2.
I'm going to start with Panel2 because it's simpler. Here is the new code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Panel2 extends JPanel {
Graphics g;
Graphics2D g2;
public int b;
public Panel2() {
setBackground(Color.YELLOW);
b = 50;
}
#Override
public void paintComponent(Graphics g) {
g2 = (Graphics2D) g;
super.paintComponent(g);
g2.setColor(Color.RED);
g2.fillRect(200, 200, 50, 50);
g2.setColor(Color.BLUE);
g2.fillRect(10, 10, 40, 40);
g2.setColor(Color.CYAN);
g2.fillRect(b, b, 40, 40);
}
public void setValue(int b) {
this.b = b;
System.out.println("B ist gleich = " + b);
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
The biggest change that I made to Panel2 is that I made g2 a class variable that all the methods can use. Instead of making the methods take a Graphics variable each time, I just made it so that they can use the one from the class. I also didn't make a new Graphics2D variable "equal" anything each time the method was called because there was no need for that. The only place I updated it in was the paintComponent() method so that I could update it once for the whole class.
Next up is Panel1. Here is the code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Panel1 extends JPanel {
public JButton button = new JButton("OK");
public JTextField field1 = new JTextField(5);
public String name;
int b;
private Panel2 pan2;
public Panel1() {
setBackground(Color.WHITE);
add(field1);
add(button);
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String op = e.getActionCommand();
if (op.equals("OK")) {
name = field1.getText();
try {
b = Integer.parseInt(name);
pan2.setValue(b);
JOptionPane.showMessageDialog(null, "Ihre Zahl = " + b);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(null, "Please enter real numbers!");
}
}
}
};
button.addActionListener(listener);
}
public void setSecondPanel(Panel2 panel) {
pan2 = panel;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
Panel1 pan1 = new Panel1();
Panel2 pan2 = new Panel2();
pan1.setSecondPanel(pan2);
frame.setSize(pan1.getPreferredSize().width + pan2.getPreferredSize().width, pan1.getPreferredSize().height);
frame.add(pan2, BorderLayout.EAST);
frame.add(pan1, BorderLayout.WEST);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
First of all, notice how I didn't create a ButtonListener. Because you're only using it once, there's no need to create a new class for it (it's also less code).
In the main() method, I made it so that it adds both panels to the opposite sides so that they won't overlap each other or anything.
Finally, I created a setSecondPanel method in the Panel1 class so that the class would have a Panel2 variable to work with at any time.

Preference activity seekbar

I have created a custom android seek bar from lukehorvat tutorial
and added to my preference xml file as below
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto" >
<PreferenceCategory
android:title="Color RGB channels"
android:order="100">
<com.heroku.android.SeekBarDialogPreference
android:defaultValue="20"
android:id="#+id/redchannel"
android:key="redchannel"
android:dialogMessage="Please select red channel:"
android:max="50"
android:title="Red channel"
custom:progressTextSuffix="%"
custom:min="1" />
<com.heroku.android.SeekBarDialogPreference
android:defaultValue="20"
android:dialogMessage="Please select green channel:"
android:max="50"
android:title="Select green channel"
custom:progressTextSuffix="%"
custom:min="1" />
<com.heroku.android.SeekBarDialogPreference
android:defaultValue="20"
android:dialogMessage="Please select blue channel:"
android:max="50"
android:title="Select blue channel"
custom:progressTextSuffix="%"
custom:min="1" />
</PreferenceCategory>
</PreferenceScreen>
And I have added to my preference activity these three seekbars as below
package com.heroku.android;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.view.View;
import android.widget.SeekBar;
public class Preferences extends PreferenceActivity
implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(com.yuldashev.android.R.xml.preferences);
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(
this);
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onDestroy() {
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(
this);
super.onDestroy();
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
}
}
The problem is all of them refers to the same seekbardialog custom class and I cannot get the values for these three seekbars seperately. I have tried to seperate them by entitling #+id in xml file but it does not works for me by findviewbyID because the custom SeekBardialogPreference does not support such an option. For example if you adding and single SeekBar by id you do
SeekBar seek1=(SeekBar)findviewByID(resource)
and you get the progress value from seek1 object.
Is there any suggestion how to do the same with custom seekbardialog below
package com.heroku.android;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
/**
* A {#link DialogPreference} that provides a user with the means to select an integer from a {#link SeekBar}, and persist it.
*
* #author lukehorvat
*
*/
public class SeekBarDialogPreference extends DialogPreference
{
private static final int DEFAULT_MIN_PROGRESS = 0;
private static final int DEFAULT_MAX_PROGRESS = 100;
private static final int DEFAULT_PROGRESS = 0;
private int mMinProgress;
private int mMaxProgress;
private int mProgress;
private CharSequence mProgressTextSuffix;
private TextView mProgressText;
private SeekBar mSeekBar;
public SeekBarDialogPreference(Context context)
{
this(context, null);
}
public SeekBarDialogPreference(Context context, AttributeSet attrs)
{
super(context, attrs);
// get attributes specified in XML
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, com.yuldashev.android.R.styleable.SeekBarDialogPreference, 0, 0);
try
{
setMinProgress(a.getInteger(com.yuldashev.android.R.styleable.SeekBarDialogPreference_min, DEFAULT_MIN_PROGRESS));
setMaxProgress(a.getInteger(com.yuldashev.android.R.styleable.SeekBarDialogPreference_android_max, DEFAULT_MAX_PROGRESS));
setProgressTextSuffix(a.getString(com.yuldashev.android.R.styleable.SeekBarDialogPreference_progressTextSuffix));
}
finally
{
a.recycle();
}
// set layout
setDialogLayoutResource(com.yuldashev.android.R.layout.preference_seek_bar_dialog);
setPositiveButtonText(android.R.string.ok);
setNegativeButtonText(android.R.string.cancel);
setDialogIcon(null);
}
#Override
protected void onSetInitialValue(boolean restore, Object defaultValue)
{
setProgress(restore ? getPersistedInt(DEFAULT_PROGRESS) : (Integer) defaultValue);
}
#Override
protected Object onGetDefaultValue(TypedArray a, int index)
{
return a.getInt(index, DEFAULT_PROGRESS);
}
#Override
protected void onBindDialogView(View view)
{
super.onBindDialogView(view);
TextView dialogMessageText = (TextView) view.findViewById(com.yuldashev.android.R.id.text_dialog_message);
dialogMessageText.setText(getDialogMessage());
mProgressText = (TextView) view.findViewById(com.yuldashev.android.R.id.text_progress);
mSeekBar = (SeekBar) view.findViewById(com.yuldashev.android.R.id.seek_bar);
mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener()
{
#Override
public void onStopTrackingTouch(SeekBar seekBar)
{
}
#Override
public void onStartTrackingTouch(SeekBar seekBar)
{
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
// update text that displays the current SeekBar progress value
// note: this does not persist the progress value. that is only ever done in setProgress()
String progressStr = String.valueOf(progress + mMinProgress);
mProgressText.setText(mProgressTextSuffix == null ? progressStr : progressStr.concat(mProgressTextSuffix.toString()));
}
});
mSeekBar.setMax(mMaxProgress - mMinProgress);
mSeekBar.setProgress(mProgress - mMinProgress);
}
public int getMinProgress()
{
return mMinProgress;
}
public void setMinProgress(int minProgress)
{
mMinProgress = minProgress;
setProgress(Math.max(mProgress, mMinProgress));
}
public int getMaxProgress()
{
return mMaxProgress;
}
public void setMaxProgress(int maxProgress)
{
mMaxProgress = maxProgress;
setProgress(Math.min(mProgress, mMaxProgress));
}
public int getProgress()
{
return mProgress;
}
public void setProgress(int progress)
{
progress = Math.max(Math.min(progress, mMaxProgress), mMinProgress);
if (progress != mProgress)
{
mProgress = progress;
persistInt(progress);
notifyChanged();
}
}
public CharSequence getProgressTextSuffix()
{
return mProgressTextSuffix;
}
public void setProgressTextSuffix(CharSequence progressTextSuffix)
{
mProgressTextSuffix = progressTextSuffix;
}
#Override
protected void onDialogClosed(boolean positiveResult)
{
super.onDialogClosed(positiveResult);
// when the user selects "OK", persist the new value
if (positiveResult)
{
int seekBarProgress = mSeekBar.getProgress() + mMinProgress;
if (callChangeListener(seekBarProgress))
{
setProgress(seekBarProgress);
}
}
}
#Override
protected Parcelable onSaveInstanceState()
{
// save the instance state so that it will survive screen orientation changes and other events that may temporarily destroy it
final Parcelable superState = super.onSaveInstanceState();
// set the state's value with the class member that holds current setting value
final SavedState myState = new SavedState(superState);
myState.minProgress = getMinProgress();
myState.maxProgress = getMaxProgress();
myState.progress = getProgress();
return myState;
}
#Override
protected void onRestoreInstanceState(Parcelable state)
{
// check whether we saved the state in onSaveInstanceState()
if (state == null || !state.getClass().equals(SavedState.class))
{
// didn't save the state, so call superclass
super.onRestoreInstanceState(state);
return;
}
// restore the state
SavedState myState = (SavedState) state;
setMinProgress(myState.minProgress);
setMaxProgress(myState.maxProgress);
setProgress(myState.progress);
super.onRestoreInstanceState(myState.getSuperState());
}
private static class SavedState extends BaseSavedState
{
int minProgress;
int maxProgress;
int progress;
public SavedState(Parcelable superState)
{
super(superState);
}
public SavedState(Parcel source)
{
super(source);
minProgress = source.readInt();
maxProgress = source.readInt();
progress = source.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags)
{
super.writeToParcel(dest, flags);
dest.writeInt(minProgress);
dest.writeInt(maxProgress);
dest.writeInt(progress);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>()
{
#Override
public SavedState createFromParcel(Parcel in)
{
return new SavedState(in);
}
#Override
public SavedState[] newArray(int size)
{
return new SavedState[size];
}
};
}
}
Thank you all!

How to add a JDialog in to desktop pane or just call from an internal frame

I am working on a project that uses MDI form in java. I have created a frame and then added a desktop pane to it. My project uses lot of internal frames. Also those internal frames require to show custom dialogs that i have created on my own. for it to be clear, i say, one jdialog has a table asking the user to select one row. but the problem is when i call the jdialog from the internal frame (with modality=true), the dialog is show on the top of main frame and not just on the top of internal frame. This makes it impossible to minimize the window when the jdialog is showing.
In my view there are 2 possible solutions (which may not possible!!).. Either the jdialog should be shown inside the dektop pane or i should create an internal frame instead of jdialog and make it appear to be modal to the parent internal frame. i.e, when i want to show the dialog, i may disable the internal frame and set the form unable to focus and then show a new internal frame on the top of this internal frame. I have been searching the forums for weeks.. but i couldn't find an answer. I hope you would have a solution. Thanks in advance, sir.
I also had the same problem, while working on a java project that works quite fine in java 6 but shown the same problem when changed to java7.
I found a solution.
I added a
dialog.setVisible(false) followed by a dialog.setVisible(true).
Then the dialog is responding to keyboard.
I am also working on an MDI app that uses a lof internal frames which show custom dialogs. I make my dialogs non-modal so that the internal frames can be iconified and/or the whole desktoppane can be minimized while the dialogs remain visible.
If you absolutely need modal behavior (i.e., you want to require the user to interact with a dialog before doing anything else) perhaps you can leave the dialog modeless but code in de facto modality.
Also, have you looked at the behavior of
setModalityType(java.awt.Dialog.ModalityType.DOCUMENT_MODAL);
?
Wow!! I got the answer from webbyt... Just avoid using internal frames.. try using the class ModalityInternalFrame (subclass of JinternalFrame).. and everything works fine.. Here is the class
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
/**
* An extended
* <code>JInternalFrame</code> that provides modality in a child/parent
* hierarchy
*
* #author webbyit
*/
public class ModalityInternalFrame extends JInternalFrame {
protected JDesktopPane desktopPane;
protected JComponent parent;
protected ModalityInternalFrame childFrame;
protected JComponent focusOwner;
private boolean wasCloseable;
public ModalityInternalFrame() {
init(); // here to allow netbeans to use class in gui builder
}
public ModalityInternalFrame(JComponent parent) {
this(parent, null);
}
public ModalityInternalFrame(JComponent parent, String title) {
this(parent, title, false);
}
public ModalityInternalFrame(JComponent parent, String title, boolean resizable) {
this(parent, title, resizable, false);
}
public ModalityInternalFrame(JComponent parent, String title, boolean resizable, boolean closeable) {
this(parent, title, resizable, closeable, false);
}
public ModalityInternalFrame(JComponent parent, String title, boolean resizable, boolean closeable,
boolean maximizable) {
this(parent, title, resizable, closeable, maximizable, false);
}
public ModalityInternalFrame(JComponent parent, String title, boolean resizable, boolean closeable,
boolean maximizable,
boolean iconifiable) {
super(title, resizable, closeable, maximizable, iconifiable);
setParentFrame(parent);
//setFocusTraversalKeysEnabled(false);
if (parent != null && parent instanceof ModalityInternalFrame) {
((ModalityInternalFrame) parent).setChildFrame(ModalityInternalFrame.this);
/*
* set focus to the new frame and show the frame Code added by Jasir
*/
try {
((ModalityInternalFrame) parent).setSelected(false);
setSelected(true);
setVisible(true);
} catch (PropertyVetoException ex) {
Logger.getLogger(ModalityInternalFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
// Add glass pane
ModalityInternalGlassPane glassPane = new ModalityInternalGlassPane(this);
setGlassPane(glassPane);
// Add frame listeners
addFrameListener();
// Add frame veto listenr
addFrameVetoListener();
init();
// calculate size and position
}
private void setParentFrame(JComponent parent) {
desktopPane = JOptionPane.getDesktopPaneForComponent(parent);
this.parent = parent == null ? JOptionPane.getDesktopPaneForComponent(parent) : parent; // default to desktop if no parent given
}
public JComponent getParentFrame() {
return parent;
}
public void setChildFrame(ModalityInternalFrame childFrame) {
this.childFrame = childFrame;
}
public ModalityInternalFrame getChildFrame() {
return childFrame;
}
public boolean hasChildFrame() {
return (childFrame != null);
}
protected void addFrameVetoListener() {
addVetoableChangeListener(new VetoableChangeListener() {
public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException {
if (evt.getPropertyName().equals(JInternalFrame.IS_SELECTED_PROPERTY)
&& evt.getNewValue().equals(Boolean.TRUE)) {
if (hasChildFrame()) {
//childFrame.setSelected(true);
if (childFrame.isIcon()) {
childFrame.setIcon(false);
}
throw new PropertyVetoException("no!", evt);
}
}
}
});
}
/**
* Method to control the display of the glass pane, dependant on the frame
* being active or not
*/
protected synchronized void addFrameListener() {
addInternalFrameListener(new InternalFrameAdapter() {
#Override
public void internalFrameActivated(InternalFrameEvent e) {
if (hasChildFrame() == true) {
getGlassPane().setVisible(true);
grabFocus();
} else {
getGlassPane().setVisible(false);
}
}
#Override
public void internalFrameOpened(InternalFrameEvent e) {
getGlassPane().setVisible(false);
try {
setSelected(true);
} catch (PropertyVetoException ex) {
Logger.getLogger(ModalityInternalFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void internalFrameClosing(InternalFrameEvent e) {
if (parent != null && parent instanceof ModalityInternalFrame) {
((ModalityInternalFrame) parent).childClosing();
}
}
});
}
/**
* Method to handle child frame closing and make this frame available for
* user input again with no glass pane visible
*/
protected void childClosing() {
setClosable(wasCloseable);
getGlassPane().setVisible(false);
if (focusOwner != null) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
moveToFront();
setSelected(true);
focusOwner.grabFocus();
} catch (PropertyVetoException ex) {
}
}
});
focusOwner.grabFocus();
}
getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
setChildFrame(null);
getDesktopPane().setSelectedFrame(this);
System.out.println(getDesktopPane().getSelectedFrame());
}
/*
* Method to handle child opening and becoming visible.
*/
protected void childOpening() {
// record the present focused component
wasCloseable = isClosable();
setClosable(false);
focusOwner = (JComponent) getMostRecentFocusOwner();
grabFocus();
getGlassPane().setVisible(true);
getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
}
#Override
public void show() {
if (parent != null && parent instanceof ModalityInternalFrame) {
// Need to inform parent its about to lose its focus due
// to child opening
((ModalityInternalFrame) parent).childOpening();
}
calculateBounds();
super.show();
}
protected void init() {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 394, Short.MAX_VALUE));
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 274, Short.MAX_VALUE));
pack();
}
public void calculateBounds() {
Dimension frameSize = getPreferredSize();
Dimension parentSize = new Dimension();
Dimension rootSize = new Dimension(); // size of desktop
Point frameCoord = new Point();
if (desktopPane != null) {
rootSize = desktopPane.getSize(); // size of desktop
frameCoord = SwingUtilities.convertPoint(parent, 0, 0, desktopPane);
parentSize = parent.getSize();
}
//setBounds((rootSize.width - frameSize.width) / 2, (rootSize.height - frameSize.height) / 2, frameSize.width, frameSize.height);
// We want dialog centered relative to its parent component
int x = (parentSize.width - frameSize.width) / 2 + frameCoord.x;
int y = (parentSize.height - frameSize.height) / 2 + frameCoord.y;
// If possible, dialog should be fully visible
int ovrx = x + frameSize.width - rootSize.width;
int ovry = y + frameSize.height - rootSize.height;
x = Math.max((ovrx > 0 ? x - ovrx : x), 0);
y = Math.max((ovry > 0 ? y - ovry : y), 0);
setBounds(x, y, frameSize.width, frameSize.height);
}
/**
* Glass pane to overlay. Listens for mouse clicks and sets selected on
* associated modal frame. Also if modal frame has no children make class
* pane invisible
*/
class ModalityInternalGlassPane extends JComponent {
private ModalityInternalFrame modalFrame;
public ModalityInternalGlassPane(ModalityInternalFrame frame) {
modalFrame = frame;
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (modalFrame.isSelected() == false) {
try {
modalFrame.setSelected(true);
if (modalFrame.hasChildFrame() == false) {
setVisible(false);
}
} catch (PropertyVetoException e1) {
//e1.printStackTrace();
}
}
}
});
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(new Color(255, 255, 255, 100));
g.fillRect(0, 0, getWidth(), getHeight());
}
}
}
But there are some problems still with focus and something else..

GWT: In a TabLayoutPanel, how do I make tabs wrap if there are too many?

I'm using GWT 2.4. I have a TabLayoutPanel to which I add tabs. Each tab contains a ScrollPanel. My question is, how do I make the tabs in the tab bar wrap to the next line if the width of the tab bar exceeds the visible width?
Thanks, - Dave
GWT's TabLayoutPanel intentionally never wraps tabs. See lines 246-248 in TabLayoutPanel.java - (line 217 defines private static final int BIG_ENOUGH_TO_NOT_WRAP = 16384). You might be able to override this, but as #milan says, it's probably not good design.
Having multiple lines is, indeed, not recommended...
However, to be able to navigate left/right on a single tab bar with many tabs, you can use this recipe:
http://devnotesblog.wordpress.com/2010/06/17/scrollable-gwt-tablayoutpanel/
And an updated implementation that doesn't use the deprecated DeferredCommand:
package whatever.you.want;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* A {#link TabLayoutPanel} that shows scroll buttons if necessary
*/
public class ScrolledTabLayoutPanel extends TabLayoutPanel {
private static final int IMAGE_PADDING_PIXELS = 4;
private LayoutPanel panel;
private FlowPanel tabBar;
private Image scrollLeftButton;
private Image scrollRightButton;
private HandlerRegistration windowResizeHandler;
private ImageResource leftArrowImage;
private ImageResource rightArrowImage;
public ScrolledTabLayoutPanel(double barHeight, Unit barUnit,
ImageResource leftArrowImage, ImageResource rightArrowImage) {
super(barHeight, barUnit);
this.leftArrowImage = leftArrowImage;
this.rightArrowImage = rightArrowImage;
// The main widget wrapped by this composite, which is a LayoutPanel with the tab bar & the tab content
panel = (LayoutPanel) getWidget();
// Find the tab bar, which is the first flow panel in the LayoutPanel
for (int i = 0; i < panel.getWidgetCount(); ++i) {
Widget widget = panel.getWidget(i);
if (widget instanceof FlowPanel) {
tabBar = (FlowPanel) widget;
break; // tab bar found
}
}
initScrollButtons();
}
#Override
public void add(Widget child, Widget tab) {
super.add(child, tab);
checkIfScrollButtonsNecessary();
}
#Override
public boolean remove(Widget w) {
boolean b = super.remove(w);
checkIfScrollButtonsNecessary();
return b;
}
#Override
protected void onLoad() {
super.onLoad();
if (windowResizeHandler == null) {
windowResizeHandler = Window.addResizeHandler(new ResizeHandler() {
#Override
public void onResize(ResizeEvent event) {
checkIfScrollButtonsNecessary();
}
});
}
}
#Override
protected void onUnload() {
super.onUnload();
if (windowResizeHandler != null) {
windowResizeHandler.removeHandler();
windowResizeHandler = null;
}
}
private ClickHandler createScrollClickHandler(final int diff) {
return new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Widget lastTab = getLastTab();
if (lastTab == null)
return;
int newLeft = parsePosition(tabBar.getElement().getStyle().getLeft()) + diff;
int rightOfLastTab = getRightOfWidget(lastTab);
// Prevent scrolling the last tab too far away form the right border,
// or the first tab further than the left border position
if (newLeft <= 0 && (getTabBarWidth() - newLeft < (rightOfLastTab + 20))) {
scrollTo(newLeft);
}
}
};
}
/** Create and attach the scroll button images with a click handler */
private void initScrollButtons() {
scrollLeftButton = new Image(leftArrowImage);
int leftImageWidth = scrollLeftButton.getWidth();
panel.insert(scrollLeftButton, 0);
panel.setWidgetLeftWidth(scrollLeftButton, 0, Unit.PX, leftImageWidth, Unit.PX);
panel.setWidgetTopHeight(scrollLeftButton, 0, Unit.PX, scrollLeftButton.getWidth(), Unit.PX);
scrollLeftButton.addClickHandler(createScrollClickHandler(+20));
scrollLeftButton.setVisible(false);
scrollRightButton = new Image(rightArrowImage);
panel.insert(scrollRightButton, 0);
panel.setWidgetLeftWidth(scrollRightButton, leftImageWidth + IMAGE_PADDING_PIXELS, Unit.PX, scrollRightButton.getWidth(), Unit.PX);
panel.setWidgetTopHeight(scrollRightButton, 0, Unit.PX, scrollRightButton.getHeight(), Unit.PX);
scrollRightButton.addClickHandler(createScrollClickHandler(-20));
scrollRightButton.setVisible(false);
}
private void checkIfScrollButtonsNecessary() {
// Defer size calculations until sizes are available, when calculating immediately after
// add(), all size methods return zero
Scheduler.get().scheduleDeferred( new Scheduler.ScheduledCommand() {
#Override
public void execute() {
boolean isScrolling = isScrollingNecessary();
// When the scroll buttons are being hidden, reset the scroll position to zero to
// make sure no tabs are still out of sight
if (scrollRightButton.isVisible() && !isScrolling) {
resetScrollPosition();
}
scrollRightButton.setVisible(isScrolling);
scrollLeftButton.setVisible(isScrolling);
}
}
);
}
private void resetScrollPosition() {
scrollTo(0);
}
private void scrollTo(int pos) {
tabBar.getElement().getStyle().setLeft(pos, Unit.PX);
}
private boolean isScrollingNecessary() {
Widget lastTab = getLastTab();
if (lastTab == null)
return false;
return getRightOfWidget(lastTab) > getTabBarWidth();
}
private int getRightOfWidget(Widget widget) {
return widget.getElement().getOffsetLeft() + widget.getElement().getOffsetWidth();
}
private int getTabBarWidth() {
return tabBar.getElement().getParentElement().getClientWidth();
}
private Widget getLastTab() {
if (tabBar.getWidgetCount() == 0)
return null;
return tabBar.getWidget(tabBar.getWidgetCount() - 1);
}
private static int parsePosition(String positionString) {
int position;
try {
for (int i = 0; i < positionString.length(); i++) {
char c = positionString.charAt(i);
if (c != '-' && !(c >= '0' && c <= '9')) {
positionString = positionString.substring(0, i);
}
}
position = Integer.parseInt(positionString);
} catch (NumberFormatException ex) {
position = 0;
}
return position;
}
}