I need to set up a click/tap event for a custom Manager.
The Manager contains a couple of elements, but I need that the whole
Manager respond to the event, so if the user taps/clicks any element
inside the Manager, the event handler should be called too.
What I have done is to attach a changeListener to a NullField that takes all width and height, but the fieldChanged method is never called
public class TestManager extends Manager{
private BitmapField _icon;
private LabelField _lblTitle;
private NullField nullField;
public TestManager(Bitmap pIcon){
super(Manager.FOCUSABLE);
_icon = new BitmapField(pIcon);
_lblTitle = new LabelField("This is the title");
nullField = new NullField(NullField.FOCUSABLE);
add(_icon);
add(_lblTitle);
add(nullField);
nullField.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
doSomething();
}
});
}
public void doSomething(){
System.out.println("do something!!");
}
public void paint(Graphics graphics)
{
graphics.setColor(Color.DELIMITER_COLOR);
graphics.fillRect(0, 20, Display.getWidth(), 50);
super.paint(graphics);
}
protected void paintBackground(Graphics arg0) {
arg0.setColor(Color.LIGHTGRAY);
arg0.fillRect(0, 0, Display.getWidth(), Display.getHeight());
super.paint(arg0);
}
protected void sublayout(int width, int height) {
setPositionChild(_icon, UIFactory.getBestX(10), UIFactory.getBestX(8));
setPositionChild(_lblTitle, UIFactory.getBestX(60), _topMarginTitle!=0?UIFactory.getBestX(_topMarginTitle):UIFactory.getBestX(15));
setPositionChild(nullField, 0, 0);
layoutChild(_icon, width, UIFactory.getBestX(50));
layoutChild(_lblTitle, width, UIFactory.getBestX(50));
layoutChild(nullField, width, height);
setExtent(width, height);
}
protected boolean navigationClick(int status, int time){
invalidate();
doSomething();
return super.navigationClick(status, time);
}
}
How should I make this whole Manager to respond a click/tap?
I'm using the API 5.0
Thanks in advance!
Question was also asked in BB forums, and I have responded there:
BlackBerry-How-to-properly-handle-a-TAP-CLICK-in-a-custom
Further to this, here is a solution to the problem:
public class BaseTouchManager extends Manager {
private FieldChangeListener _callBack;
public BaseTouchManager(FieldChangeListener pCallBack) {
super(0);
_callBack = pCallBack;
setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
_callBack.fieldChanged(field, context);
}
});
add(new NullField(Field.FOCUSABLE));
}
protected void sublayout(int width, int height) {
setExtent(Display.getHeight()/2, 100);
}
protected boolean navigationClick(int status, int time) {
fieldChangeNotify(1);
return true;
}
public void paint(Graphics graphics) {
if(_callBack!=null){
if(isFocus())
graphics.setColor(Color.LIGHTBLUE);
else
graphics.setColor(Color.WHITE);
graphics.fillRect(this.getWidth() - 10,
this.getHeight() - 10,
10, 10);
}
super.paint(graphics);
}
}
The original poster actually suggested a different solution, review the BB forum post for more.
Related
Huy guys, I have a weird problem.
I'm kinda new to swing and java applications.
I'm trying to make a custom UI jslider that changes a jlabel text when you move the thumb.
My problem is: when I use the addChangeListener(), it creates a weird glitch when moving the thumb.
If I don't use it, it works perfectly fine.
How can I update the JLabel without using the change listener or how can I fix this graphic bug?
Most of this code comes from stackoverflow since I don't know much about painting components.
See pictures at the button to better understand the problem
Thanks!
The code in my jpanel
JSlider slider = new JSlider(SwingConstants.HORIZONTAL, 1, 10, 1) {
#Override
public void updateUI() {
setUI(new CustomSliderUI(this));
}
};
// If I comment this line the visual glitch is gone when moving the thumb, but the value doesnt update
slider.addChangeListener((event) -> RAM_LABEL.setText(slider.getValue() + " Gb"));
slider.setMinorTickSpacing(1);
slider.setMajorTickSpacing(10);
slider.setSnapToTicks(true);
slider.setBounds(96, 317, 300, 35);
slider.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
slider.setOpaque(false);
this.add(slider);
The custom slider ui class
private static class CustomSliderUI extends BasicSliderUI
{
private static final int TRACK_HEIGHT = 8;
private static final int TRACK_ARC = 5;
private static final Dimension THUMB_SIZE = new Dimension(22, 20);
private final RoundRectangle2D.Float trackShape = new RoundRectangle2D.Float();
private final Image knob;
public CustomSliderUI(final JSlider b)
{
super(b);
knob = Swinger.getResource("knob.png");
}
#Override
protected void calculateTrackRect() {
super.calculateTrackRect();
trackRect.y = trackRect.y + (trackRect.height - TRACK_HEIGHT) / 2;
trackRect.height = TRACK_HEIGHT;
trackShape.setRoundRect(trackRect.x, trackRect.y, trackRect.width, trackRect.height, TRACK_ARC, TRACK_ARC);
}
#Override
protected void calculateThumbLocation() {
super.calculateThumbLocation();
thumbRect.y = trackRect.y + (trackRect.height - thumbRect.height) / 2;
}
#Override
protected Dimension getThumbSize() {
return THUMB_SIZE;
}
#Override
public void paint(final Graphics g, final JComponent c) {
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
super.paint(g, c);
}
#Override
public void paintTrack(final Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Shape clip = g2.getClip();
boolean inverted = slider.getInverted();
// Paint shadow.
g2.setColor(new Color(170, 170 ,170));
g2.fill(trackShape);
// Paint track background.
g2.setColor(new Color(200, 200 ,200));
g2.setClip(trackShape);
trackShape.y += 1;
g2.fill(trackShape);
trackShape.y = trackRect.y;
g2.setClip(clip);
// Paint selected track.
boolean ltr = slider.getComponentOrientation().isLeftToRight();
if (ltr) inverted = !inverted;
int thumbPos = thumbRect.x + thumbRect.width / 2;
if (inverted) {
g2.clipRect(0, 0, thumbPos, slider.getHeight());
} else {
g2.clipRect(thumbPos, 0, slider.getWidth() - thumbPos, slider.getHeight());
}
g2.setColor(Swinger.getTransparentWhite(0));
g2.fill(trackShape);
g2.setClip(clip);
}
#Override
public void paintThumb(final Graphics g)
{
g.drawImage(knob, thumbRect.x, thumbRect.y, null);
}
#Override
public void paintFocus(final Graphics g) {}
}
Visual glitch when you are moving the cursor, as soon as you stop pressing the mouse it goes back to normal
Regular cursor / when I move it without the change listener
Solved. I went with drawing my own background it was simplier.
private static class CustomSliderUI extends BasicSliderUI
{
private static final Dimension THUMB_SIZE = new Dimension(22, 20);
private final Image thumb, background;
private final JSlider slider;
public CustomSliderUI(final JSlider b)
{
super(b);
slider = b;
thumb = Swinger.getResource("thumb.png");
background = Swinger.getResource("slider.png");
}
#Override
protected Dimension getThumbSize() {
return THUMB_SIZE;
}
#Override
public void paintTrack(final Graphics g) {
g.drawImage(background, 10, 11, 280, 10, null);
}
#Override
public void paintThumb(final Graphics g)
{
g.drawImage(thumb, thumbRect.x, thumbRect.y, null);
slider.repaint();
}
#Override
public void paintFocus(final Graphics g) {}
}
JSlider slider = new JSlider(SwingConstants.HORIZONTAL, 1, 10, 1) {
#Override
public void updateUI() {
setUI(new CustomSliderUI(this));
}
};
slider.addChangeListener((event) -> RAM_LABEL.setText(slider.getValue() + " Gb"));
slider.setBounds(96, 317, 300, 35);
slider.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
slider.setOpaque(false);
this.add(slider);
So I'm painting a couple custom JComponets in a grid. like a simple battleship game. However I wanted to add a transparency to them. It renders in great the first time but if I call repaint then the alpha level goes away. I can then resize the frame and it automatically updates it and has the correct transparency.
public class Cell extends JComponent implements MouseListener{
public static int CELL_SIZE=50;
private boolean hit = false;
private boolean hasShip = false;
private GridPoint location;
private boolean highlighted = false;
private GameBoard parent;
public static final Color HIT = new Color(Color.RED.getRed(),Color.RED.getGreen(),Color.RED.getBlue(),123);
public static final Color MISS = new Color(80,100,200,123);
public static final Color DEFAULT = new Color(0,0,(150),123);
public static final Color HIGHLIGHT = new Color(255,255,255,50);
public static final Color BORDER = new Color(0,0,40,123);
public Cell()
{
setSize(Cell.CELL_SIZE,Cell.CELL_SIZE);
}
public Cell(GridPoint g, GameBoard p)
{
setOpaque(false);
addMouseListener(this);
parent = p;
setGridLocation(g);
setLocation(CELL_SIZE*location.getX(), CELL_SIZE*location.getY());
setSize(Cell.CELL_SIZE,Cell.CELL_SIZE);
}
public void paintComponent(Graphics g)
{
if(hit == false)
{
if(highlighted)
{
g.setColor(HIGHLIGHT);
g.fillRect(0, 0, Cell.CELL_SIZE, Cell.CELL_SIZE);
}
g.setColor(DEFAULT);
g.fillRect(0, 0, Cell.CELL_SIZE, Cell.CELL_SIZE);
}
else
{
if(hasShip)
{
g.setColor(Cell.HIT);
g.fillRect(0, 0, Cell.CELL_SIZE, Cell.CELL_SIZE);
}
else
{
g.setColor(Cell.MISS);
g.fillRect(0, 0, Cell.CELL_SIZE, Cell.CELL_SIZE);
}
}
g.setColor(Cell.BORDER);
g.drawRect(0, 0, Cell.CELL_SIZE, Cell.CELL_SIZE);
}
public GridPoint getGridLocation() {
return location;
}
public void setGridLocation(GridPoint location) {
this.location = location;
}
#Override
public void mouseClicked(MouseEvent e) {
hit = true;
repaint();
}
#Override
public void mouseEntered(MouseEvent e)
{
highlighted = true;
repaint();
}
#Override
public void mouseExited(MouseEvent e)
{
highlighted = false;
repaint();
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
}
If you add the following lines to start of your paintComponent method, it should work.
float alpha = 0.2f;
((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
alpha 0.0f means completely transparent, 1.0f means not transparent.
Okay I got the answer. Sorry it was a bug in some other area of code. for some reason the tiles were rendering under the JPanels Background Color. All I had to do was set the JPanel in the Back To Transparent.
According to documentation the ExtendViewportshould extend the view and keep the aspect ratio, but whenever I try Implemented this viewPort Ive got two bars in the side of the phone screen. (this is sample background image,with some text and button on it to check how stretch will be).
Code:
public class Overlap2d extends Game {
public static float ASPECT_RATIO ;
public static final int GAME_SCREEN_WIDTH = 40;
public static final int GAME_SCREEN_HEIGHT = 80;
#Override
public void create () {
ASPECT_RATIO=(float)Gdx.graphics.getWidth()/(float)Gdx.graphics.getHeight() ;
ScreenManager.getScreenManager().init(this);
ScreenManager.getScreenManager().showScreen( ScreenName.MAIN_MENU );
}}
public abstract class AbstractScreen extends Stage implements Screen {
public AbstractScreen() {
super(new ExtendViewport(GAME_SCREEN_WIDTH,GAME_SCREEN_HEIGHT,new OrthographicCamera()));
}
public abstract void buildStage();
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 1, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
super.act(delta);
super.draw();
}
#Override
public void resize(int width, int height) {
getViewport().update(width,height);
}
#Override
public void show() {
Gdx.input.setInputProcessor(this);
}
#Override
public void resume() {}
#Override
public void pause() {}
#Override
public void hide() {}}
public class MenuScreen extends AbstractScreen{
private Texture txtrBg;
public MenuScreen() {
super();
txtrBg = new Texture( Gdx.files.internal("test.png") );
}
#Override
public void buildStage() {
getCamera().position.set(GAME_SCREEN_WIDTH / 2, GAME_SCREEN_HEIGHT / 2, 0);
Image bg = new Image(txtrBg);
bg.setSize(GAME_SCREEN_WIDTH,GAME_SCREEN_HEIGHT);
bg.setPosition(0,0);
addActor(bg);
}
#Override
public void dispose() {
super.dispose();
txtrBg.dispose();
}}
public static final int GAME_SCREEN_WIDTH = 40;
public static final int GAME_SCREEN_HEIGHT = 80;
you're using width and height ratio 1:2 but only very view device fits in this ratio so why don't you try 48 and 80 as viewport width and height.
Question is almost same so explanation can fit here also
https://stackoverflow.com/a/43398153/3445320
I am new to graphics and japplets, and I made a rectangle that goes across the screen. But for some reason, it just draws a line across, not removing the old instance of the rectangle once it moves.
Main:
public class Main extends JApplet implements Runnable {
private static final long serialVersionUID = 1L;
private static int width = 900;
private static int height = 600;
public static int fps = 60;
public Thread thread = new Thread(this);
public static Ailoid ailoid = new Ailoid();
public void init() {
setSize(width, height);
setBackground(Color.white);
ailoid.setLocation(new Location(100, 100));
AlienManager.registerAlien(ailoid);
}
public void paint(Graphics g) {
g.setColor(Color.green);
for (Alien alien : AlienManager.getAliens()) {
Location loc = alien.getLocation();
int x = loc.getX();
int y = loc.getY();
g.fillRect(x, y, 10, 20);
}
}
// Thread start
#Override
public void start() {
thread.start();
}
// Thread stop
#SuppressWarnings("deprecation")
#Override
public void destroy() {
thread.stop();
}
#Override
public void run() {
while (true) {
Updater.run();
repaint();
try {
// 1000 divided by fps to get frames per millisecond
Thread.sleep(1000 / fps);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Updater:
public class Updater {
public static void run() {
for (Alien alien : AlienManager.getAliens()) {
Location loc = alien.getLocation();
int x = loc.getX();
int y = loc.getY();
alien.setLocation(new Location(x, y));
}
}
}
Why doesn't it remove the old graphics? thank you!
Your main problem is that your paint(...) method does not call the super method, the method that allows the component to redraw its contents:
public void paint(Graphics g) {
super.paint(g);
//....
Having said that, you're far better off not drawing in a top level window but rather in the paintComponent method of a JPanel that is displayed by the applet. If you do this correction, then do the same thing -- call the super method.
class MyPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//....
As an aside, this code:
public class Updater {
public static void run() {
for (Alien alien : AlienManager.getAliens()) {
Location loc = alien.getLocation();
int x = loc.getX();
int y = loc.getY();
alien.setLocation(new Location(x, y));
}
}
}
Doesn't look like it's moving things all that much. In fact per this code, your aliens should stay completely still.
Edit
Also, this is never code, code you should never have in your application:
#SuppressWarnings("deprecation")
#Override
public void destroy() {
thread.stop();
}
There's a reason that thread's stop() method is deprecated and should never be called. If you're curious as to why, please check out the API.
I'm making a BlackBerry OS 6+ application and I need to draw a solid square of a specific color (given at runtime) but it should be add-able to a VerticalFieldManager. So I think custom-drawing using a Graphics object is not an option.
I already tried setting the background color of a LabelField to the color I want and adding that LabelField to the VerticalFieldManager. To get the square-shaped appearance, I tried overriding the getPreferredWidth() and getPreferredHeight of LabelField to return a higher value (eg: 150). But although the width was correctly displayed, the height stayed the same no matter what value I returned.
So is there any way I can achieve this? In summary, what I want is:
A solid square-shaped block of color (color decided at runtime).
Which should be added to a VerticalFieldManager.
Thanks in advance!
try this code , Pass in the color in the constructor.
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
public class CustomField extends Field
{
private int backgroundColour;
private int fieldWidth;
private int fieldHeight;
private int padding = 8;
public CustomField(int color)
{
super(Field.FOCUSABLE);
fieldHeight = 100;
fieldWidth = 100;
this.setPadding(2, 2, 2, 2);
this.backgroundColour=color;
}
public int getPreferredWidth()
{
return fieldWidth;
}
public int getPreferredHeight()
{
return fieldHeight;
}
protected void layout(int arg0, int arg1)
{
setExtent(getPreferredWidth(), getPreferredHeight());
}
protected void drawFocus(Graphics graphics, boolean on)
{
}
protected void paint(Graphics graphics)
{
graphics.setColor(backgroundColour);
graphics.fillRect(0, 0, fieldWidth, fieldHeight);
}
}
VerticalFieldManager vfm = new VerticalFieldManager();
Field f = new Field() {
protected void paint(Graphics graphics) {
graphics.setBackgroundColor(Color.RED);
graphics.clear();
graphics.drawRect(10, 10, 100, 100);
graphics.fillRect(10, 10, 100, 100);
}
protected void layout(int width, int height) {
// TODO Auto-generated method stub
setExtent(200, 200);
}
};
vfm.add(f);
add(vfm);