Does this component exist in Java? It is a a button with an attached combo box.
I have similar component which I developed in one of my own projects.
Please replace all the custom components (Like - CToolBarButton to JButton, CPanel to JPanel, CButton to JButton) wherever required. You also can use custion UI classes to get the desired look and feel.
package com.custom.ui.base.control;
import com.custom.ui.base.border.ToolbarButtonOptionsBorder;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
/**
* This is Options button in for ToolBar. This Toolbar button can contain other toolbar buttons those
* would be displayed in the popup
*
* #version 1.0.0.1 (Jul 29, 2010)
* #author Arindam Roy
*/
public class CToolbarButtonOptions extends CToolBarButton implements ActionListener, PopupMenuListener {
/**
* Holds number of buttons in the Popup
*/
int count = 0;
/**
* Holds the Columns in the popup
*/
private int maxColumnCount = 3;
/**
* Creates new form BeanForm
*/
public CToolbarButtonOptions() {
initComponents();
init();
}
/**
* Initializes additional components in this screen
*/
private void init() {
jPopupMenu.add(dmPanel);
setListeners();
}
/**
* Adds listeners to the components
*/
private void setListeners() {
this.addActionListener(this);
this.jPopupMenu.addPopupMenuListener(this);
}
/**
* Adds a Toolbar button in the popup
*
* #param toolBarButton <code>CToolBarButton</code> instance to add in the popup
* #see CToolBarButton
* #see #remove(com.dbm.base.control.DMToolBarButton)
*/
public void add(CToolBarButton toolBarButton) {
dmPanel.add(toolBarButton);
toolBarButton.addActionListener(this);
count++;
updateLayout();
}
/**
* Returns components of Option button popup menu
*
* #return <code>Component[]</code> that contains components of popup menu
*/
public Component[] getPopupComponents() {
return dmPanel.getComponents();
}
/**
* Removes a Toolbar button from the popup
*
* #param toolBarButton <code>CToolBarButton</code> instance to remove from the popup
* #see CToolBarButton
* #see #add(com.dbm.base.control.DMToolBarButton)
*/
public void remove(CToolBarButton toolBarButton) {
toolBarButton.removeActionListener(this);
count--;
dmPanel.remove(toolBarButton);
}
/**
* Recognize the columns and rows to place popup menu buttons in the Popup
*/
private void updateLayout() {
if (dmPanel.getLayout() instanceof GridLayout) {
int row = (count / getMaxColumnCount());
if (count % getMaxColumnCount() > 0) {
row++;
}
int column = count >= maxColumnCount ? maxColumnCount : count;
if (!(row == 0 && column == 0)) {
((GridLayout) dmPanel.getLayout()).setRows(row);
((GridLayout) dmPanel.getLayout()).setColumns(column);
}
}
}
/**
* This method is called from within the constructor to
* initialize the form.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jPopupMenu = new javax.swing.JPopupMenu();
dmPanel = new com.custom.ui.base.container.CPanel();
jPopupMenu.setBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(38, 144, 72)), javax.swing.BorderFactory.createLineBorder(new java.awt.Color(255, 255, 255))));
dmPanel.setLayout(new java.awt.GridLayout(1, 1, 0, 1));
setBorder(new ToolbarButtonOptionsBorder());
setPreferredSize(new java.awt.Dimension(25, 8));
}// </editor-fold>//GEN-END:initComponents
/**
* Action Handler for Action Events
*
* #param e <code>ActionEvent</code> instance that holds the event details
*/
public void actionPerformed(ActionEvent e) {
if (e.getSource() == this) {
jPopupMenu.show(this, 2, this.getBounds().y + this.getBounds().height + 1);
} else {
jPopupMenu.setVisible(false);
}
}
/**
* Returns the number of columns, according to that the Popup menu buttons are placed
*
* #return <code>int</code> column count in the popup menu for button placement
* #see #setMaxColumnCount(int)
*/
public int getMaxColumnCount() {
return maxColumnCount;
}
/**
* Sets the number of columns, according to that the Popup menu buttons are placed
*
* #param maxColumnCount <code>int</code> column count in the popup menu for button
* placement, to set
* #see #getMaxColumnCount()
*/
public void setMaxColumnCount(int maxColumnCount) {
this.maxColumnCount = maxColumnCount;
updateLayout();
}
/**
* Action handler for Popup menu listener. This method handles the event of "popup menu visible"
*
* #param e <code>PopupMenuEvent</code> instance that holds the event details
*/
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
this.getModel().setRollover(true);
}
/**
* Action handler for Popup menu listener. This method handles the event of "popup menu visible"
*
* #param e <code>PopupMenuEvent</code> instance that holds the event details
*/
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
this.getModel().setRollover(false);
}
/**
* Action handler for Popup menu listener. This method handles the event of "popup menu visible"
*
* #param e <code>PopupMenuEvent</code> instance that holds the event details
*/
public void popupMenuCanceled(PopupMenuEvent e) {
this.getModel().setRollover(false);
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private com.custom.ui.base.container.CPanel dmPanel;
private javax.swing.JPopupMenu jPopupMenu;
// End of variables declaration//GEN-END:variables
}
This will look like:
Custom Border class:
package com.custom.ui.base.border;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Insets;
import javax.swing.border.EmptyBorder;
/**
* This border for toolbar button component holds group of buttons. Clicking on this, one popup comes that
* contains all the options buttons available against this toolbar button.
*
* #version 1.0.0.1 (Sep 15, 2010)
* #author Arindam Roy
*/
public class ToolbarButtonOptionsBorder extends EmptyBorder {
/**
* Indicates width of the Down arrow icon width
*/
private int optionArrowWidth = 7;
/**
* Creates new instance of ToolbarButtonOptionsBorder
*/
public ToolbarButtonOptionsBorder() {
super(new Insets(4, 4, 4, 8));
}
/**
* Paints the border for the specified component with the specified position and size.
*
* #param c the component for which this border is being painted
* #param g the paint graphics
* #param x the x position of the painted border
* #param y the y position of the painted border
* #param width the width of the painted border
* #param height the height of the painted border
*/
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
super.paintBorder(c, g, x, y, width, height);
g.setColor(Color.LIGHT_GRAY);
int xPoints[] = new int[]{x + width - optionArrowWidth - 1, x + width - 1, x + width - 2 - (optionArrowWidth / 2)};
int yPoints[] = new int[]{y + (height / 2) - 1, y + (height / 2) - 1, y + (height / 2) + 3};
g.fillPolygon(xPoints, yPoints, xPoints.length);
g.drawLine(x + width - optionArrowWidth - 2, y + 5, x + width - optionArrowWidth - 2, height - 3);
g.setColor(Color.BLACK);
xPoints = new int[]{x + width - optionArrowWidth, x + width - 2, x + width - 2 - (optionArrowWidth / 2)};
yPoints = new int[]{y + (height / 2) - 1, y + (height / 2) - 1, y + (height / 2) + 2};
g.fillPolygon(xPoints, yPoints, xPoints.length);
}
}
Related
The goal to write the values of columns into JTable vertically. I read about DefaultTableCellRenderer, VerticalTableHeaderCellRenderer() but cannot implement it. Here is my code:
//=========================================================
private JScrollPane getTablePane() {
if (tablePane == null) {
tablePane = new JScrollPane();
tablePane.setRowHeaderView(getTableDictionary());
tablePane.setViewportView(getTableDictionary());
}
return tablePane;
}
//=============================================================
private JTable getTableDictionary(){
if (table == null) {
rowVector = new String[colCount];
for(int i=0; i<colCount;i++) {rowVector[i]="";}
data = new DefaultTableModel(rowVector, 0);
for (int i = 0; i < rowCount; i++) { data.addRow(rowVector); }
table = new JTable(data);
table.getTableHeader().setDefaultRenderer(new VerticalTableHeaderCellRenderer());
for(int i=1; i<colCount; i++) { table.getColumnModel().getColumn(i).setPreferredWidth(withCol);}
table.setSelectionForeground(Color.BLACK);
table.setSelectionBackground(Color.YELLOW);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setAutoscrolls(true);
table.setColumnSelectionAllowed(false);
table.setRowSelectionAllowed(true);
/* DefaultTableCellRenderer defaultTableCellRenderer = new DefaultTableCellRenderer();
int bg = table.getTableHeader().getBackground().getRGB();
defaultTableCellRenderer.setBackground(Color.getHSBColor(125, 125, 125)); //задаем цвет столбца
table.getColumnModel().getColumn(0).setCellRenderer(defaultTableCellRenderer);
*/
return table;
}
Where is my mistake? Thank you
I read more resources and I found a decision, it works. I need to implement a render for that and call it when I am locating the table on the JScrollPane. It means that column header is processing apart from a JTable using datamodel. Also, I can define the height of the columns.
private JScrollPane getTablePane() {
if (tablePane == null) {
tablePane = new JScrollPane();
tablePane.setRowHeaderView(getTableDictionary());
tablePane.setViewportView(getTableDictionary());
tablePane.setColumnHeader(new JViewport() {
#Override public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
d.height = rowColumnHeigth; // Col header Height
return d;
}
});
}
return tablePane;
}
Also, I need for that additional classes:
/**
* #(#)DefaultTableHeaderCellRenderer.java 1.0 02/24/09
*/
import java.awt.Component;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.RowSorter.SortKey;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
/**
* A default cell renderer for a JTableHeader.
* <P>
* DefaultTableHeaderCellRenderer attempts to provide identical behavior to the
* renderer which the Swing subsystem uses by default, the Sun proprietary
* class sun.swing.table.DefaultTableCellHeaderRenderer.
* <P>
* To apply any desired customization, DefaultTableHeaderCellRenderer may be
* suitably extended.
*
* #author Darryl
*/
public class DefaultTableHeaderCellRenderer extends DefaultTableCellRenderer {
/**
* Constructs a <code>DefaultTableHeaderCellRenderer</code>.
* <P>
* The horizontal alignment and text position are set as appropriate to a
* table header cell, and the opaque property is set to false.
*/
public DefaultTableHeaderCellRenderer() {
setHorizontalAlignment(CENTER);
setHorizontalTextPosition(LEFT);
setVerticalAlignment(BOTTOM);
setOpaque(false);
}
/**
* Returns the default table header cell renderer.
* <P>
* If the column is sorted, the approapriate icon is retrieved from the
* current Look and Feel, and a border appropriate to a table header cell
* is applied.
* <P>
* Subclasses may overide this method to provide custom content or
* formatting.
*
* #param table the <code>JTable</code>.
* #param value the value to assign to the header cell
* #param isSelected This parameter is ignored.
* #param hasFocus This parameter is ignored.
* #param row This parameter is ignored.
* #param column the column of the header cell to render
* #return the default table header cell renderer
*/
#Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
JTableHeader tableHeader = table.getTableHeader();
if (tableHeader != null) {
setForeground(tableHeader.getForeground());
}
setIcon(getIcon(table, column));
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
return this;
}
/**
* Overloaded to return an icon suitable to the primary sorted column, or null if
* the column is not the primary sort key.
*
* #param table the <code>JTable</code>.
* #param column the column index.
* #return the sort icon, or null if the column is unsorted.
*/
protected Icon getIcon(JTable table, int column) {
SortKey sortKey = getSortKey(table, column);
if (sortKey != null && table.convertColumnIndexToView(sortKey.getColumn()) == column) {
switch (sortKey.getSortOrder()) {
case ASCENDING:
return UIManager.getIcon("Table.ascendingSortIcon");
case DESCENDING:
return UIManager.getIcon("Table.descendingSortIcon");
}
}
return null;
}
/**
* Returns the current sort key, or null if the column is unsorted.
*
* #param table the table
* #param column the column index
* #return the SortKey, or null if the column is unsorted
*/
protected SortKey getSortKey(JTable table, int column) {
RowSorter rowSorter = table.getRowSorter();
if (rowSorter == null) {
return null;
}
List sortedColumns = rowSorter.getSortKeys();
if (sortedColumns.size() > 0) {
return (SortKey) sortedColumns.get(0);
}
return null;
}
}
Also:
/**
* #(#)VerticalLabelUI.java 1.0 02/18/09
*/
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicLabelUI;
/**
* A UI delegate for JLabel that rotates the label 90є
* <P>
* Extends {#link BasicLabelUI}.
* <P>
* The only difference between the appearance of labels in the Basic and Metal
* L&Fs is the manner in which diabled text is painted. As VerticalLabelUI
* does not override the method paintDisabledText, this class can be adapted
* for Metal L&F by extending MetalLabelUI instead of BasicLabelUI.
* <P>
* No other changes are required.
*
* #author Darryl
*/
public class VerticalLabelUI extends BasicLabelUI {
private boolean clockwise = false;
// see comment in BasicLabelUI
Rectangle verticalViewR = new Rectangle();
Rectangle verticalIconR = new Rectangle();
Rectangle verticalTextR = new Rectangle();
protected static VerticalLabelUI verticalLabelUI =
new VerticalLabelUI();
private final static VerticalLabelUI SAFE_VERTICAL_LABEL_UI =
new VerticalLabelUI();
/**
* Constructs a <code>VerticalLabelUI</code> with the default anticlockwise
* rotation
*/
public VerticalLabelUI() {
}
/**
* Constructs a <code>VerticalLabelUI</code> with the desired rotation.
* <P>
* #param clockwise true to rotate clockwise, false for anticlockwise
*/
public VerticalLabelUI(boolean clockwise) {
this.clockwise = clockwise;
}
/**
* #see ComponentUI#createUI(javax.swing.JComponent)
*/
public static ComponentUI createUI(JComponent c) {
if (System.getSecurityManager() != null) {
return SAFE_VERTICAL_LABEL_UI;
} else {
return verticalLabelUI;
}
}
/**
* Overridden to always return -1, since a vertical label does not have a
* meaningful baseline.
*
* #see ComponentUI#getBaseline(JComponent, int, int)
*/
#Override
public int getBaseline(JComponent c, int width, int height) {
super.getBaseline(c, width, height);
return -1;
}
/**
* Overridden to always return Component.BaselineResizeBehavior.OTHER,
* since a vertical label does not have a meaningful baseline
*
* #see ComponentUI#getBaselineResizeBehavior(javax.swing.JComponent)
*/
#Override
public Component.BaselineResizeBehavior getBaselineResizeBehavior(
JComponent c) {
super.getBaselineResizeBehavior(c);
return Component.BaselineResizeBehavior.OTHER;
}
/**
* Transposes the view rectangles as appropriate for a vertical view
* before invoking the super method and copies them after they have been
* altered by {#link SwingUtilities#layoutCompoundLabel(FontMetrics, String,
* Icon, int, int, int, int, Rectangle, Rectangle, Rectangle, int)}
*/
#Override
protected String layoutCL(JLabel label, FontMetrics fontMetrics,
String text, Icon icon, Rectangle viewR, Rectangle iconR,
Rectangle textR) {
verticalViewR = transposeRectangle(viewR, verticalViewR);
verticalIconR = transposeRectangle(iconR, verticalIconR);
verticalTextR = transposeRectangle(textR, verticalTextR);
text = super.layoutCL(label, fontMetrics, text, icon,
verticalViewR, verticalIconR, verticalTextR);
viewR = copyRectangle(verticalViewR, viewR);
iconR = copyRectangle(verticalIconR, iconR);
textR = copyRectangle(verticalTextR, textR);
return text;
}
/**
* Transforms the Graphics for vertical rendering and invokes the
* super method.
*/
#Override
public void paint(Graphics g, JComponent c) {
Graphics2D g2 = (Graphics2D) g.create();
if (clockwise) {
g2.rotate(Math.PI / 2, c.getSize().width / 2, c.getSize().width / 2);
} else {
g2.rotate(-Math.PI / 2, c.getSize().height / 2, c.getSize().height / 2);
}
super.paint(g2, c);
}
/**
* Returns a Dimension appropriate for vertical rendering
*
* #see ComponentUI#getPreferredSize(javax.swing.JComponent)
*/
#Override
public Dimension getPreferredSize(JComponent c) {
return transposeDimension(super.getPreferredSize(c));
}
/**
* Returns a Dimension appropriate for vertical rendering
*
* #see ComponentUI#getMaximumSize(javax.swing.JComponent)
*/
#Override
public Dimension getMaximumSize(JComponent c) {
return transposeDimension(super.getMaximumSize(c));
}
/**
* Returns a Dimension appropriate for vertical rendering
*
* #see ComponentUI#getMinimumSize(javax.swing.JComponent)
*/
#Override
public Dimension getMinimumSize(JComponent c) {
return transposeDimension(super.getMinimumSize(c));
}
private Dimension transposeDimension(Dimension from) {
return new Dimension(from.height, from.width + 2);
}
private Rectangle transposeRectangle(Rectangle from, Rectangle to) {
if (to == null) {
to = new Rectangle();
}
to.x = from.y;
to.y = from.x;
to.width = from.height;
to.height = from.width;
return to;
}
private Rectangle copyRectangle(Rectangle from, Rectangle to) {
if (to == null) {
to = new Rectangle();
}
to.x = from.x;
to.y = from.y;
to.width = from.width;
to.height = from.height;
return to;
}
}
Also:
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.Icon;
import javax.swing.JTable;
import javax.swing.RowSorter.SortKey;
import javax.swing.SortOrder;
import javax.swing.UIManager;
/**
* A renderer for a JTableHeader with text rotated 90В° counterclockwise.
* <P>
* Extends {#link DefaultTableHeaderCellRenderer}.
*
* #see VerticalLabelUI
* #author Darryl
*/
public class VerticalTableHeaderCellRenderer
extends DefaultTableHeaderCellRenderer {
/**
* Constructs a <code>VerticalTableHeaderCellRenderer</code>.
* <P>
* The horizontal and vertical alignments and text positions are set as
* appropriate to a vertical table header cell.
*/
public VerticalTableHeaderCellRenderer() {
setHorizontalAlignment(LEFT);
setHorizontalTextPosition(CENTER);
setVerticalAlignment(CENTER);
setVerticalTextPosition(TOP);
setUI(new VerticalLabelUI());
}
/**
* Overridden to return a rotated version of the sort icon.
*
* #param table the <code>JTable</code>.
* #param column the colummn index.
* #return the sort icon, or null if the column is unsorted.
*/
#Override
protected Icon getIcon(JTable table, int column) {
SortKey sortKey = getSortKey(table, column);
if (sortKey != null && table.convertColumnIndexToView(sortKey.getColumn()) == column) {
SortOrder sortOrder = sortKey.getSortOrder();
switch (sortOrder) {
case ASCENDING:
return VerticalSortIcon.ASCENDING;
case DESCENDING:
return VerticalSortIcon.DESCENDING;
}
}
return null;
}
/**
* An icon implementation to paint the contained icon rotated 90В° clockwise.
* <P>
* This implementation assumes that the L&F provides ascending and
* descending sort icons of identical size.
*/
private enum VerticalSortIcon implements Icon {
ASCENDING(UIManager.getIcon("Table.ascendingSortIcon")),
DESCENDING(UIManager.getIcon("Table.descendingSortIcon"));
private final Icon icon;// = ;
private VerticalSortIcon(Icon icon) {
this.icon = icon;
}
/**
* Paints an icon suitable for the header of a sorted table column,
* rotated by 90В° clockwise. This rotation is applied to compensate
* the rotation already applied to the passed in Graphics reference
* by the VerticalLabelUI.
* <P>
* The icon is retrieved from the UIManager to obtain an icon
* appropriate to the L&F.
*
* #param c the component to which the icon is to be rendered
* #param g the graphics context
* #param x the X coordinate of the icon's top-left corner
* #param y the Y coordinate of the icon's top-left corner
*/
#Override
public void paintIcon(Component c, Graphics g, int x, int y) {
int maxSide = Math.max(getIconWidth(), getIconHeight()+(Integer)getIconHeight()/4);
Graphics2D g2 = (Graphics2D) g.create(x, y, maxSide, maxSide);
g2.rotate((Math.PI / 2));
g2.translate(0, -maxSide);
icon.paintIcon(c, g2, 0, 0);
g2.dispose();
}
/**
* Returns the width of the rotated icon.
*
* #return the <B>height</B> of the contained icon
*/
#Override
public int getIconWidth() {
return icon.getIconHeight();
}
/**
* Returns the height of the rotated icon.
*
* #return the <B>width</B> of the contained icon
*/
#Override
public int getIconHeight() {
return icon.getIconWidth();
}
}
}
It works fine for me. Thank you!
Also, it looks like:
I have a JPanel with an overriden paintComponent. I want to make certain elements that I manually draw on this panel focusable so that people using assistive technologies could use my application using keyboard.
If you could give me a few pointers that would be awesome.
You can do the following:
Convert your elements into JComponents.
Set the LayoutManager of your panel to null. You will then add all your components/elements into this panel and you can move them freelly around with the method Component.setBounds(...).
Add a MouseListener in your panel which will transfer the focus to the selected component, for each mouse press.
You can determine which component was pressed by calling the method Component.getComponentAt(Point) inside the MouseListener of your panel.
Simple example:
Make a component with the standard behaviour of showing the user if it has focus or not. In my example-code below this class is FocusableComponent extends JComponent, which draws a blue rectangle around the component if it has focus (this is done inside the method FocusableComponent.paintComponent(Graphics)).
Then, for each distinct "element" you draw, subclass FocusableComponent and override its paintComponent(Graphics) method to paint the element. Make sure you call "super.paintComponent(Graphics)" inside there for the blue rectangle to be drawn (if it has focus).
Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FocusablePaintComps {
private static abstract class FocusableComponent extends JComponent {
#Override protected void paintComponent(final Graphics g) {
super.paintComponent(g);
if (hasFocus()) {
final Color prevColor = g.getColor();
g.setColor(Color.BLUE);
g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g.setColor(prevColor);
}
}
}
private static class FocusableComponent1 extends FocusableComponent {
#Override protected void paintComponent(final Graphics g) {
super.paintComponent(g);
g.fillOval(0, 0, getWidth() - 1, getHeight() - 1);
}
}
private static class FocusableComponent2 extends FocusableComponent {
#Override protected void paintComponent(final Graphics g) {
super.paintComponent(g);
final int w = getWidth(), h = getHeight();
g.fillRect(20, 20, w - 40, h - 40);
g.fillArc(10, 10, w - 1, h - 1, 60, 150);
}
}
private static class YourPanel extends JPanel {
private Component previousFocusedComponent = null;
private YourPanel() {
super(null); //Null LayoutManager. This is important to be able to
//move added components around freelly (with the method setBounds(...)).
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(final MouseEvent evt) {
final Component src = getComponentAt(evt.getPoint());
if (src instanceof FocusableComponent) {
final FocusableComponent fc = (FocusableComponent) src;
fc.requestFocusInWindow(); //Transfer focus to the pressed component.
if (previousFocusedComponent != null)
previousFocusedComponent.repaint(); //Repaint the last (without focus now).
setComponentZOrder(fc, 0); //Update: To make fc paint over all others as
//the user http://stackoverflow.com/users/131872/camickr commented.
fc.repaint(); //Repaint the new (with focus now).
previousFocusedComponent = fc;
}
else { //If clicked on empty space, or a non-FocusableComponent:
requestFocusInWindow(); //Tranfer focus to somewhere else (e.g. the panel itself).
if (previousFocusedComponent != null) {
previousFocusedComponent.repaint(); //Repaint the last (without focus now).
previousFocusedComponent = null;
}
}
}
});
setPreferredSize(new Dimension(250, 250));
add(new FocusableComponent1(), Color.RED, new Rectangle(10, 10, 200, 20));
add(new FocusableComponent1(), Color.GREEN, new Rectangle(40, 150, 50, 70));
add(new FocusableComponent2(), Color.GRAY, new Rectangle(60, 125, 90, 100));
add(new FocusableComponent2(), Color.MAGENTA, new Rectangle(150, 60, 80, 150));
}
private void add(final FocusableComponent fc, final Color fgColor, final Rectangle bounds) {
fc.setForeground(fgColor);
add(fc);
fc.setBounds(bounds);
}
}
public static void main(final String[] args) {
final JFrame frame = new JFrame("Focused Paint Comps");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new YourPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Screenshot:
Some notes:
The sequence in which the focus is transfered in relation to the sequence in which the rapaint()s are called inside mousePressed(...) determines which component will have the blue rectanlge around it, and which not.
Method Component.getElementAt(Point) does not "see through" transparent/non-opaque pixels.
Update:
Note: This update is an optional expansion (but maybe a more java-contract-consistent - let me put it) of the above solution. You may read only one of two implementations (either the following "update" one with RandomLayout, either the above "pre-update" one with null LayoutManager).
Follows an update of the above code, which uses a custom LayoutManager to lay-out the components in the container, as suggested by user "Andrew Thompson" in comments.
The only difference from the above code is that instead of setting to null the LayoutManager upon construction of the YourPanel, a new instance of the custom LayoutManager is used and instead of setting the bounds for each component, you only need to set its size.
I have named the custom LayoutManager to RandomLayout and it places all the components of the container in random positions, taking into account the size of the components and the Insets of the container (this is demonstrated by the added Border in the YourPanel).
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class FocusablePaintComps {
private static abstract class FocusableComponent extends JComponent {
#Override protected void paintComponent(final Graphics g) {
super.paintComponent(g);
if (hasFocus()) {
final Color prevColor = g.getColor();
g.setColor(Color.BLUE);
g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g.setColor(prevColor);
}
}
}
private static class FocusableComponent1 extends FocusableComponent {
#Override protected void paintComponent(final Graphics g) {
super.paintComponent(g);
g.fillOval(0, 0, getWidth() - 1, getHeight() - 1);
}
}
private static class FocusableComponent2 extends FocusableComponent {
#Override protected void paintComponent(final Graphics g) {
super.paintComponent(g);
final int w = getWidth(), h = getHeight();
g.fillRect(20, 20, w - 40, h - 40);
g.fillArc(10, 10, w - 1, h - 1, 60, 150);
}
}
private static class YourPanel extends JPanel {
private Component previousFocusedComponent = null;
private YourPanel() {
super(new RandomLayout()); //RandomLayout: custom LayoutManager which lays
//out the components in random positions (takes Insets into account).
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(final MouseEvent evt) {
final Component src = getComponentAt(evt.getPoint());
if (src instanceof FocusableComponent) {
final FocusableComponent fc = (FocusableComponent) src;
fc.requestFocusInWindow(); //Transfer focus to the pressed component.
if (previousFocusedComponent != null)
previousFocusedComponent.repaint(); //Repaint the last (without focus now).
setComponentZOrder(fc, 0); //Update: To make fc paint over all others as
//the user http://stackoverflow.com/users/131872/camickr commented.
fc.repaint(); //Repaint the new (with focus now).
previousFocusedComponent = fc;
}
else { //If clicked on empty space, or a non-FocusableComponent:
requestFocusInWindow(); //Tranfer focus to somewhere else (e.g. the panel itself).
if (previousFocusedComponent != null) {
previousFocusedComponent.repaint(); //Repaint the last (without focus now).
previousFocusedComponent = null;
}
}
}
});
setBorder(new LineBorder(Color.LIGHT_GRAY, 20));
setPreferredSize(new Dimension(300, 250));
add(new FocusableComponent1(), Color.RED, new Dimension(200, 20));
add(new FocusableComponent1(), Color.GREEN, new Dimension(50, 70));
add(new FocusableComponent2(), Color.GRAY, new Dimension(90, 100));
add(new FocusableComponent2(), Color.MAGENTA, new Dimension(80, 150));
}
private void add(final FocusableComponent fc, final Color fgColor, final Dimension size) {
add(fc);
fc.setForeground(fgColor);
fc.setSize(size);
}
}
public static void main(final String[] args) {
final JFrame frame = new JFrame("Focused Paint Comps");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new YourPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Update's "RandomLayout":
And the custom LayoutManager itself with JavaDoc (may be big, but reusable hopefully):
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Point;
import java.util.Random;
/**
* A {#link java.awt.LayoutManager} which lays out randomly all the {#link java.awt.Component}s
* of its parent, taking into consideration the parent's {#link java.awt.Insets}.
* <p>
* Use {#link #setRandomizeOnce(boolean)} method to determine if the lastly laid-out parent will
* be only laid-out randomly once and not for each {#link #layoutContainer(java.awt.Container)}
* subsequent call for the same parent, or the opposite.
* </p>
*/
public class RandomLayout implements LayoutManager {
/**
* The {#link java.awt.Container} which was lastly laid-out.
*/
private Container lastParent;
/**
* The {#link java.awt.Insets} of {#code lastParent} the last time it was laid-out.
*/
private Insets lastInsets;
/**
* If {#code true} then this {#link java.awt.LayoutManager} keeps track of the
* {#link java.awt.Container}s laid-out to make sure that {#code lastParent} is
* only laid-out once. If the another {#link java.awt.Container} is laid-out, other
* than {#code lastParent}, then its components are laid-out randomly and the
* {#link java.awt.Container} becomes the {#code lastParent}.
*/
private boolean randomizeOnce;
/**
* Normal constructor of {#code RandomLayout} with explicit value for {#code randomizeOnce}.
*
* #param randomizeOnce {#code true} if the lastly laid-out parent will be only laid-out
* randomly once and not for each {#link #layoutContainer(java.awt.Container)} subsequent call
* for the same parent, otherwise {#code false} and each call to
* {#link #layoutContainer(java.awt.Container)} will lay out randomly the {#link java.awt.Container}.
*/
public RandomLayout(final boolean randomizeOnce) {
this.randomizeOnce = randomizeOnce;
}
/**
* Default constructor of {#code RandomLayout} with {#code randomizeOnce} set to {#code true}.
*/
public RandomLayout() {
this(true);
}
/**
* If {#code true} then this {#link java.awt.LayoutManager} keeps track of the
* {#link java.awt.Container}s laid-out to make sure that {#code lastParent} is
* only laid-out once. If the another {#link java.awt.Container} is laid-out, other
* than {#code lastParent}, then its components are laid-out randomly and the
* {#link java.awt.Container} becomes the {#code lastParent}.
*
* #param randomizeOnce {#code true} if the lastly laid-out parent will be only laid-out
* randomly once and not for each {#link #layoutContainer(java.awt.Container)} subsequent call
* for the same parent, otherwise {#code false}.
*/
public void setRandomizeOnce(final boolean randomizeOnce) {
this.randomizeOnce = randomizeOnce;
}
/**
* Tells if the lastly laid-out parent will be only laid-out randomly once and not for each
* {#link #layoutContainer(java.awt.Container)} subsequent call for the same parent, or the
* opposite.
*
* #return {#code true} if the lastly laid-out parent will be only laid-out randomly once and
* not for each {#link #layoutContainer(java.awt.Container)} subsequent call for the same
* parent, otherwise {#code false}.
*/
public boolean isRandomizeOnce() {
return randomizeOnce;
}
/**
* #return The {#link java.awt.Container} which was lastly laid-out.
*/
protected Container getLastParent() {
return lastParent;
}
/**
* #return The {#link java.awt.Insets} of {#code lastParent} the last time it was laid-out.
* #see #getLastParent()
*/
protected Insets getLastInsets() {
return lastInsets;
}
/**
* Adds the specified component with the specified name to the layout.
* #param name The name of the component.
* #param comp The {#link java.awt.Component} to be added.
*/
public void addLayoutComponent(final String name,
final Component comp) {
}
/**
* Removes the specified component from the layout.
* #param comp The {#link java.awt.Component} to be removed.
*/
public void removeLayoutComponent(final Component comp) {
}
/**
* {#inheritDoc}
* #return The preferred size dimensions for the specified {#link java.awt.Container}.
*/
#Override
public Dimension preferredLayoutSize(final Container parent) {
final Dimension prefDim = minimumLayoutSize(parent);
prefDim.width += 2; //+2 to spare.
prefDim.height += 2; //+2 to spare.
return prefDim;
}
/**
* {#inheritDoc}
* #return The minimum size dimensions for the specified {#link java.awt.Container}.
*/
#Override
public Dimension minimumLayoutSize(final Container parent) {
final Dimension minDim = new Dimension();
final int childCnt = parent.getComponentCount();
for (int i=0; i<childCnt; ++i)
applyBigger(minDim, getPreferredSize(parent, parent.getComponent(i)));
final Insets parInsets = parent.getInsets();
minDim.width += (parInsets.left + parInsets.right);
minDim.height += (parInsets.top + parInsets.bottom);
return minDim;
}
/**
* {#inheritDoc}. If the another {#link java.awt.Container} is laid-out, other
* than {#code lastParent}, then its components are laid-out randomly and the
* {#link java.awt.Container} becomes the {#code lastParent}.
*/
#Override
public void layoutContainer(final Container parent) {
if (parent == null)
throw new IllegalArgumentException("Cannot lay out null.");
if (isRandomizeOnce() && lastParent == parent) { //At least take care of insets (if they have changed).
final Insets parentInsets = parent.getInsets();
if (!lastInsets.equals(parentInsets)) {
final int offx = parentInsets.left - lastInsets.left,
offy = parentInsets.top - lastInsets.top;
final int childCnt = parent.getComponentCount();
for (int i=0; i<childCnt; ++i) {
final Component child = parent.getComponent(i);
final Point childLoca = child.getLocation();
childLoca.x += offx;
childLoca.y += offy;
child.setLocation(childLoca);
}
lastInsets = parentInsets;
}
}
else
layoutContainerRandomly(parent);
}
/**
* Explicitly lays out randomly the specified container.
* <p>
* This is equivalent of calling:
* <pre>
* boolean isRand1 = randomLayout.isRandomizeOnce();
* randomLayout.setRandomizeOnce(false);
* randomLayout.layoutContainer(parent);
* randomLayout.setRandomizeOnce(isRand1);
* </pre>
* {#code parent} becomes {#code lastParent}.
* </p>
* #param parent The container to be laid out.
*/
public void layoutContainerRandomly(final Container parent) { //Place each child at a random location for the "new" parent (lastParent != parent).
if (parent == null)
throw new IllegalArgumentException("Cannot lay out null.");
reset();
final Dimension parentSize = parent.getSize();
final Insets parentInsets = parent.getInsets();
final Dimension childSize = new Dimension();
final Point childLoca = new Point();
final Random rand = new Random();
final int childCnt = parent.getComponentCount();
for (int i=0; i<childCnt; ++i) {
final Component child = parent.getComponent(i);
child.getSize(childSize);
childLoca.x = parentInsets.left + 1;
childLoca.y = parentInsets.top + 1;
final int xBound = parentSize.width - parentInsets.left - parentInsets.right - childSize.width,
yBound = parentSize.height - parentInsets.top - parentInsets.bottom - childSize.height;
if (xBound > 0)
childLoca.x += rand.nextInt(xBound);
if (yBound > 0)
childLoca.y += rand.nextInt(yBound);
child.setLocation(childLoca);
}
lastParent = parent;
lastInsets = parentInsets;
}
/**
* Invalidates the tracking of the lastly laid-out {#link java.awt.Container} and its last
* {#link java.awt.Insets}.
* #see #getLastParent()
* #see #getLastInsets()
*/
protected void reset() {
lastParent = null;
lastInsets = null;
}
private static void applyBigger(final Dimension inputOutput,
final Dimension input) {
if (inputOutput != null && input != null) {
inputOutput.width = (int) Math.max(inputOutput.width, input.width);
inputOutput.height = (int) Math.max(inputOutput.height, input.height);
}
}
private static void applyIfBetter(final Dimension inputOutput,
final Dimension input) {
if (inputOutput != null && input != null
&& (input.width > inputOutput.width
|| input.height > inputOutput.height)) {
inputOutput.width = input.width;
inputOutput.height = input.height;
}
}
/**
* Tries to determine the best size for {#code child}.
* #param parnt The parent {#link java.awt.Container} being laid-out.
* #param child The child {#link java.awt.Component} of {#code parnt} being laid-out.
* #return A preferred size for the {#code child} to be laid-out.
*/
protected static Dimension getPreferredSize(final Container parnt,
final Component child) {
final Dimension minDim = new Dimension();
if (child != null) {
applyIfBetter(minDim, child.getMinimumSize());
applyIfBetter(minDim, child.getSize());
applyIfBetter(minDim, child.getPreferredSize());
}
return minDim;
}
}
Updated screenshot:
And here is the new screenshot (no big visual differences):
Note for the update:
Be aware that this is my first custom LayoutManager, but I have read the documentation, and also GridLayout and SpringLayout as examples (because, in my oppinion, LayoutManager's documentation is not enough) and of course I tested it. As it is wright now, I cannot find any problem with it. Any suggestions or proposals for improvements will be appreciated of course.
Edit:Code is available on
github(https://github.com/goxr3plus/DragAdjustableLabel)
Question
I made a custom control in javaFX which I don't know how to name it. It actually does not exist in the javaFX packages but I saw it in other programs like LMMS where it's been used to control the volume.
The problem
When the mouse is reaching the top or bottom of the monitor screen nothing can be done. Have a look at the code to see what I'm talking about. How to solve the problem? Feel free to edit the title to a more appropriate ones.
import java.awt.Robot;
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class FX3 extends Application {
#Override
public void start(Stage stage) throws Exception {
// Root-BorderPane
BorderPane borderPane = new BorderPane(new VolumeLabel(0, 100));
borderPane.setStyle("-fx-background-color:black;");
// Scene
stage.setScene(new Scene(borderPane, 200, 200, Color.BLACK));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
// TODO SpecialLabel
class VolumeLabel extends Label {
int screenX, screenY, previousY, minimumValue, maximumValue;
IntegerProperty currentValue = new SimpleIntegerProperty(15);
/**
* Constructor
*/
public VolumeLabel(int minimumValue, int maximumValue) {
this.minimumValue = minimumValue;
this.maximumValue = maximumValue;
textProperty().bind(currentValue.asString().concat(" %"));
setStyle(
"-fx-background-color:white; -fx-text-fill:black; -fx-padding:-2 8 -2 8; -fx-background-radius: 15; -fx-font-size:20; -fx-cursor:open-hand;");
// MouseListeners
setOnMousePressed(m -> {
screenX = (int) m.getScreenX();
screenY = (int) m.getScreenY();
//setCursor(Cursor.NONE); //Uncommend this line to make the cursor invisible
});
setOnMouseDragged(m -> {
setCurrentValue(
getCurrentValue() + (m.getScreenY() == previousY ? 0 : m.getScreenY() > previousY ? -1 : 1));
previousY = (int) m.getScreenY();
});
setOnMouseReleased(m -> {
// When the mouse is released -> move it to the initial position
try {
new Robot().mouseMove(screenX, screenY);
} catch (Exception e) {
e.printStackTrace();
}
setCursor(Cursor.OPEN_HAND);
});
}
/**
* Returns the Current Value of VolumeLabel
*
* #return
*/
public int getCurrentValue() {
return currentValue.get();
}
/**
* Setting the Current Value of VolumeLabel
*
* #param value
*/
public void setCurrentValue(int value) {
//System.out.println("Value:" + value + ", CurrentValue:" + currentValue.get());
if (value >= minimumValue && value <= maximumValue)
currentValue.set(value);
}
}
}
Here is the answer(the code also in on github):
import java.awt.Robot;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.Cursor;
import javafx.scene.control.Label;
import javafx.stage.Screen;
/**
* A custom Node which is working like a Slider. <br>
* <b>!</b> When you hold the mouse on it and drag upside the value is
* increased. <br>
* <b>!</b> When you hold the mouse on it and drag down side the value is
* decreased.
*
* <br>
* Usage:
*
* <pre>
* <code>
* //initialize
* DragAdjustableLabel dragAdjustableLabel = new DragAdjustableLabel(10, 0, 100);
*
* //add it for example to a BorderPane
* primaryStage.setScene(new Scene(new BorderPane(dragAdjustableLabel)));
*</code>
* </pre>
*
* #author GOXR3PLUS
* #version 1.0
*/
public class DragAdjustableLabel extends Label {
// Variables
private int screenX;
private int screenY;
private int previousY;
private int minimumValue;
private int maximumValue;
/**
* The current value of the DragAdjustableLabel
*/
private IntegerProperty currentValue;
/**
* Constructor
*
* #param minimumValue
* Minimum Value that the slider can have
* #param maximumValue
* Maximum Value that the slider can have
*/
public DragAdjustableLabel(int currentValue, int minimumValue, int maximumValue) {
this.currentValue = new SimpleIntegerProperty(currentValue);
this.minimumValue = minimumValue;
this.maximumValue = maximumValue;
// Add a costume style class
this.getStyleClass().add("drag-adjustable-label");
setCursor(Cursor.OPEN_HAND);
textProperty().bind(this.currentValue.asString().concat(" %"));
// when the mouse is pressed
setOnMousePressed(m -> {
screenX = (int) m.getScreenX();
screenY = (int) m.getScreenY();
setCursor(Cursor.NONE); // comment this line to make the cursor
// visible
});
// when the mouse is dragged
setOnMouseDragged(m -> {
// calculate the monitor height
double screenHeight = Screen.getPrimary().getBounds().getHeight();
// !if the mouse has reached the the top of the monitor
// or
// ! if the mouse has reached the bottom of the monitor
if (m.getScreenY() <= 0 || m.getScreenY() + 10 >= screenHeight) {
resetMouse();
return;
}
// Calculate the current value
setCurrentValue(
getCurrentValue() + (m.getScreenY() == previousY ? 0 : m.getScreenY() > previousY ? -1 : 1));
previousY = (int) m.getScreenY();
});
// when the mouse is released
setOnMouseReleased(m -> {
resetMouse();
setCursor(Cursor.OPEN_HAND);
});
}
/**
* Reset the mouse to the default position(which is the center of the
* element)
*
* #param x
* #param y
*/
private void resetMouse() {
try {
new Robot().mouseMove(screenX, screenY);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Set the current value
*
* #param value
*/
public void setCurrentValue(int value) {
// if the value is between the limits
if (value >= minimumValue && value <= maximumValue)
currentValue.set(value);
}
public int getCurrentValue() {
return currentValue.get();
}
public IntegerProperty currentValueProperty() {
return currentValue;
}
}
This question already has answers here:
glTranslatef not working within glBegin .. glEnd
(2 answers)
Closed 7 years ago.
I'm attempting to draw a red square with LGJWL (native OpenGL bindings for Java) in Java. I receive a 1282 error from OpenGL and my square does not appear.
Below is (what I believe to be) the basic implementation for what I'm trying to do.
// begin drawing quads
glBegin(GL11.GL_QUADS);
// set color
glColor4d(255, 0, 0, 255);
// draw rectangle vertices
glVertex2i(0, 0);
glVertex2i(100, 0);
glVertex2i(100, 100);
glVertex2i(0, 100);
glEnd();
Following is what I'm trying to do in practice.
public class WindowComponent extends Component {
/** Window color */
private Color color = new Color();
/**
* Sets the window's color
* #param r red
* #param b blue
* #param g green
* #param a alpha
*/
public void setColor(int r, int g, int b, int a) {
color.set(r, g, b, a);
}
/**
* #see Component#renderComponent()
*/
#Override
protected void renderComponent() {
// begin drawing quads
begin(GL11.GL_QUADS);
// set color
GL11.glColor4ub(color.getRedByte(), color.getGreenByte(), color.getBlueByte(), color.getAlphaByte());
// draw rectangle vertices
GL11.glVertex2i(0, 0);
GL11.glVertex2i(getWidth(), 0);
GL11.glVertex2i(getWidth(), getHeight());
GL11.glVertex2i(0, getHeight());
end();
}
}
is an extension of...
public abstract class Component {
/** Dimension of component */
private Dimension size = new Dimension();
/** Position of component */
private Vector2f position = new Vector2f();
/**
* Gets width
* #return width
*/
public int getWidth() {
return size.getWidth();
}
/**
* Gets height
* #return height
*/
public int getHeight() {
return size.getHeight();
}
/**
* Gets size
* #return size
*/
public Dimension getSize() {
return size;
}
/**
* Gets X position
* #return X position
*/
public float getX() {
return position.getX();
}
/**
* Gets Y position
* #return Y position
*/
public float getY() {
return position.getY();
}
/**
* Gets position vector
* #return position vector
*/
public Vector2f getPosition() {
return position;
}
/**
* Sets width
* #param width width
*/
public void setWidth(int width) {
size.setWidth(width);
}
/**
* Sets height
* #param height height
*/
public void setHeight(int height) {
size.setHeight(height);
}
/**
* Sets size
* #param width width
* #param height height
*/
public void setSize(int width, int height) {
size.setSize(width, height);
}
/**
* Sets X position
* #param x X position
*/
public void setX(float x) {
position.setX(x);
}
/**
* Sets Y position
* #param y Y position
*/
public void setY(float y) {
position.setY(y);
}
/**
* Sets position
* #param x X position
* #param y Y position
*/
public void setPosition(float x, float y) {
position.set(x, y);
}
/**
* Begins drawing and does parent translations
* #param mode drawing mode
*/
protected void begin(int mode) {
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glBegin(mode);
GL11.glTranslatef(getX(), getY(), 0);
}
/**
* Ends drawing and does parent translations
*/
protected void end() {
GL11.glTranslatef(-getX(), -getY(), 0);
GL11.glEnd();
GL11.glEnable(GL11.GL_TEXTURE_2D);
}
/**
* Applies pre-rendering checks then renders the component
*/
public void render() {
renderComponent();
}
/**
* Component rendering code here
*/
protected abstract void renderComponent();
}
and I'm initializing this all with...
WindowComponent window = new WindowComponent();
window.setSize(100, 100);
window.setPosition(100, 100);
window.setColor(255, 0, 0, 255);
window.render();
In begin:
GL11.glBegin(mode);
GL11.glTranslatef(getX(), getY(), 0);
You cannot call glTranslate in between glBegin and glEnd; move it to before.
im using the Canvas class to make a screensaver as a schoolproject.
But the window generated by Canvas doesnt show my objects on it (current time)
until i minimize it an resize it again. After that all things works fine.
so what is wrong?
thank you for coming answers!
with kind regards
leon
those are the classes, i peronally think that the problem is in the class Start or BufferedCanvas
import java.awt.*;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class Start
{
int fensterX = 900;
int fensterY = 700;
Farbengenerator fg = new Farbengenerator();
BufferedCanvas c =newBufferedCanvas("Bild",fensterX,fensterY);
Zeit z = new Zeit();
SchriftParameter sp = new SchriftParameter();
public void zeichneText(){
double x = 100;
double y = 100;
double fy =0.01;
double fx =0.02;
int red=0;
int green=0;
int blue=0;
double colourGrowRate=0.05;
String uhr;
c.setFont(sp.setzteSchrift());
c.setForegroundColour(Color.BLACK);
c.setBackgroundColour(Color.WHITE);
for(int i=0;i<100;i++){
c.drawString("Starting...",(int)x,(int)y);
c.updateAndShow();
try{Thread.sleep(50);}
catch(Exception e){};
c.updateAndShow();
}
CreateButton d = new CreateButton();
d.run();
while(true) {
c.erase();
uhr = z.erstelleZeit();
c.drawString(uhr,(int)x,(int)y);
if((int)x >fensterX-93 || (int)x <5){
fx = fx * (-1);
red=fg.gibROT();
green=fg.gibGRUEN();
blue=fg.gibBLAU();
Color colour = new Color(red,green,blue);
c.setForegroundColour(colour);
}
if((int)y > fensterY-1 || (int)y < 46){
fy = fy * (-1);
red=fg.gibROT();
green=fg.gibGRUEN();
blue=fg.gibBLAU();
Color colour = new Color(red,green,blue);
c.setForegroundColour(colour);
}
if((int)colourGrowRate>=1){
fg.generiereFarbe();
colourGrowRate = 0.05;
}
colourGrowRate=colourGrowRate+colourGrowRate;
x = x + fx;
y = y + fy;
c.updateAndShow();
}
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferStrategy;
public class BufferedCanvas
{
private JFrame frame;
private CanvasPane canvas;
private Graphics2D graphic;
private Color backgroundColour;
private Image canvasImage;
BufferStrategy buff;
/**
* Create a BufferedCanvas with default height,
width and background colour
* (300, 300, white).
* #param title title to appear in Canvas Frame
*/
public BufferedCanvas(String title)
{
this(title, 300, 300, Color.white);
}
/**
* Create a BufferedCanvas with default background colour (white).
* #param title title to appear in Canvas Frame
* #param width the desired width for the canvas
* #param height the desired height for the canvas
*/
public BufferedCanvas(String title, int width, int height)
{
this(title, width, height, Color.white);
}
/**
* Create a BufferedCanvas.
* #param title title to appear in Canvas Frame
* #param width the desired width for the canvas
* #param height the desired height for the canvas
* #param bgClour the desired background colour of the canvas
*/
public BufferedCanvas(String title, int width, int height, Color bgColour)
{
frame = new JFrame();
canvas = new CanvasPane();
frame.setContentPane(canvas);
frame.setTitle(title);
canvas.setPreferredSize(new Dimension(width, height));
backgroundColour = bgColour;
frame.pack();
frame.createBufferStrategy(2);
buff = frame.getBufferStrategy();
graphic = (Graphics2D)buff.getDrawGraphics();
setVisible(true);
}
/**
* Set the canvas visibility and brings canvas to the front of screen
* when made visible. This method can also be used to bring an already
* visible canvas to the front of other windows.
* #param visible boolean value representing the desired visibility of
* the canvas (true or false)
*/
public void setVisible(boolean visible)
{
if(graphic == null) {
// first time: instantiate the offscreen image and fill it with
// the background colour
Dimension size = canvas.getSize();
canvasImage = canvas.createImage(size.width, size.height);
graphic = (Graphics2D)canvasImage.getGraphics();
graphic.setColor(backgroundColour);
graphic.fillRect(0, 0, size.width, size.height);
graphic.setColor(Color.black);
}
frame.setVisible(true);
}
/**
* Update the canvas and show the new image.
*/
public void updateAndShow(){
buff.show();
}
/**
* Provide information on visibility of the Canvas.
* #return true if canvas is visible, false otherwise
*/
public boolean isVisible()
{
return frame.isVisible();
}
/**
* Draw a given shape onto the canvas.
* #param shape the shape object to be drawn on the canvas
*/
public void draw(Shape shape)
{
graphic.draw(shape);
//canvas.repaint();
}
/**
* Fill the internal dimensions of a given shape with the current
* foreground colour of the canvas.
* #param shape the shape object to be filled
*/
public void fill(Shape shape)
{
graphic.fill(shape);
//canvas.repaint();
}
/**
* Erase the whole canvas.
*/
public void erase()
{
Color original = graphic.getColor();
graphic.setColor(backgroundColour);
Dimension size = canvas.getSize();
graphic.fill(new Rectangle(0, 0, size.width, size.height));
graphic.setColor(original);
//canvas.repaint();
}
/**
* Erase a given shape's interior on the screen.
* #param shape the shape object to be erased
*/
public void erase(Shape shape)
{
Color original = graphic.getColor();
graphic.setColor(backgroundColour);
graphic.fill(shape); // erase by filling background colour
graphic.setColor(original);
//canvas.repaint();
}
/**
* Erases a given shape's outline on the screen.
* #param shape the shape object to be erased
*/
public void eraseOutline(Shape shape)
{
Color original = graphic.getColor();
graphic.setColor(backgroundColour);
graphic.draw(shape); // erase by drawing background colour
graphic.setColor(original);
//canvas.repaint();
}
/**
* Draws an image onto the canvas.
* #param image the Image object to be displayed
* #param x x co-ordinate for Image placement
* #param y y co-ordinate for Image placement
* #return returns boolean value representing whether the image was
* completely loaded
*/
public boolean drawImage(Image image, int x, int y)
{
boolean result = graphic.drawImage(image, x, y, null);
//canvas.repaint();
return result;
}
/**
* Draws a String on the Canvas.
* #param text the String to be displayed
* #param x x co-ordinate for text placement
* #param y y co-ordinate for text placement
*/
public void drawString(String text, int x, int y)
{
graphic.drawString(text, x, y);
//canvas.repaint();
}
/**
* Erases a String on the Canvas.
* #param text the String to be displayed
* #param x x co-ordinate for text placement
* #param y y co-ordinate for text placement
*/
public void eraseString(String text, int x, int y)
{
Color original = graphic.getColor();
graphic.setColor(backgroundColour);
graphic.drawString(text, x, y);
graphic.setColor(original);
//canvas.repaint();
}
/**
* Draws a line on the Canvas.
* #param x1 x co-ordinate of start of line
* #param y1 y co-ordinate of start of line
* #param x2 x co-ordinate of end of line
* #param y2 y co-ordinate of end of line
*/
public void drawLine(int x1, int y1, int x2, int y2)
{
graphic.drawLine(x1, y1, x2, y2);
//canvas.repaint();
}
/**
* Draws a dot/pixel on the Canvas.
* #param x x co-ordinate of dot
* #param y y co-ordinate of dot
*/
public void drawDot(int x, int y)
{
graphic.drawLine(x, y, x, y);
//canvas.repaint();
}
/**
* Sets the foreground colour of the Canvas.
* #param newColour the new colour for the foreground of the Canvas
*/
public void setForegroundColour(Color newColour)
{
graphic.setColor(newColour);
}
/**
* Returns the current colour of the foreground.
* #return the colour of the foreground of the Canvas
*/
public Color getForegroundColour()
{
return graphic.getColor();
}
/**
* Sets the background colour of the Canvas.
* #param newColour the new colour for the background of the Canvas
*/
public void setBackgroundColour(Color newColour)
{
backgroundColour = newColour;
graphic.setBackground(newColour);
}
/**
* Returns the current colour of the background
* #return the colour of the background of the Canvas
*/
public Color getBackgroundColour()
{
return backgroundColour;
}
/**
* changes the current Font used on the Canvas
* #param newFont new font to be used for String output
*/
public void setFont(Font newFont)
{
graphic.setFont(newFont);
}
/**
* Returns the current font of the canvas.
* #return the font currently in use
**/
public Font getFont()
{
return graphic.getFont();
}
/**
* Sets the size of the canvas.
* #param width new width
* #param height new height
*/
public void setSize(int width, int height)
{
canvas.setPreferredSize(new Dimension(width, height));
Image oldImage = canvasImage;
canvasImage = canvas.createImage(width, height);
graphic = (Graphics2D)canvasImage.getGraphics();
graphic.drawImage(oldImage, 0, 0, null);
frame.pack();
}
/**
* Returns the size of the canvas.
* #return The current dimension of the canvas
*/
public Dimension getSize()
{
return canvas.getSize();
}
/**
* Waits for a specified number of milliseconds before finishing.
* This provides an easy way to specify a small delay which can be
* used when producing animations.
* #param milliseconds the number
*/
public void wait(int milliseconds)
{
try
{
Thread.sleep(milliseconds);
}
catch (Exception e)
{
// ignoring exception at the moment
}
}
/************************************************************************
* Nested class CanvasPane - the actual canvas component contained in the
* Canvas frame. This is essentially a JPanel with added capability to
* refresh the image drawn on it.
*/
private class CanvasPane extends JPanel
{
public void paint(Graphics g)
{
g.drawImage(canvasImage, 0, 0, null);
}
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
public class CreateButton extends JFrame implements ActionListener{
public void run() {
createAndShowGUI();
}
public CreateButton() {
// set layout for the frame
this.getContentPane().setLayout(new FlowLayout());
JButton button1 = new JButton();
button1.setText("closeApp");
//set actionlisteners for the buttons
button1.addActionListener(this);
// define a custom short action command for the button
button1.setActionCommand("closeApp");
// add buttons to frame
add(button1);
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new CreateButton();
//Display the window.
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent ae) {
String action = ae.getActionCommand();
if (action.equals("closeApp")) {
System.exit(1);
}
}
}
import java.awt.*;
public class SchriftParameter
{
public Font setzteSchrift(){
Font f = new Font("Fixed",1,24);
return (f);
}
}
public class Farbengenerator
{
int r=0;
int g=0;
int b=0;
public void generiereFarbe(){
if (r<255&&g==0&&b==0){
r++;
}
else if (r==255&&g<255&&b==0){
g++;
}
else if (r>0&&g==255&&b==0){
r= r-1;
}
else if (r==0&&g==255&&b<255){
b++;
}
else if (r==0&&g>0&&b==255){
g=g-1;
}
else if (r<255&&g==0&&b==255){
r++;
}
else if (r==255&&g==0&&b>0){
b=b-1;
}
}
public int gibROT () {
return(r);
}
public int gibGRUEN () {
return(g);
}
public int gibBLAU () {
return(b);
}
}
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class Zeit
{
public String erstelleZeit(){
DateFormat df = new SimpleDateFormat("HH:mm:ss");
Date d = new Date();
String uhr = df.format(d);
return (uhr);
}
}