How to scroll a ScrollPane in code? - java

I’m trying to make a scrollwheel component like this in LibGDX:
I’m using ScrollPane since it has input and fling handling built in. I have an image for the scrollwheel that is divided into 14 sections, the scrollpane itself is two sections shorter so that there will be one section on the right and left sides that it can scroll to in either direction. Once the scroll position reaches the end in either direction I want to reset the scroll position back to the center. Doing this over and over again should create the illusion of an infinite scrolling wheel (hopefully).
The problem I’m having is how to position the ScrollPane in code to reset the image once it reaches either end. So far nothing I have tried to set the scroll position has worked. I’ve tried setScrollX() and scrollTo() methods. I’ve also tried setting the size of the scrollpane to be various sizes (same size as image and two sections smaller than the image). I’ve tried calling layout, invalidate, and pack on the scrollpane to make sure it is laid out correctly before I set the scroll value. I thought that updateVisualScroll() might force it to update the scroll position, but this also has no effect.
No matter what I do it simply ignores all of my calls to change the scroll position so I’m clearly missing something. In my code below I'm trying to get the scrollwheel to start in the center of the image and instead it's starting position is all the way at the left.
I also need to be able to get the current scroll position to detect when it has reached either end. I tried overriding the act() method and printing out scrollPane.getX(), but this value was always “0” even when I manually clicked and dragged it to scroll the ScrollPane.
The scrolling does work when manually clicking and dragging, so I believe the ScrollPane is set up correctly, I just can’t get it to scroll within the code.
Here is my code, and for simplicity I took all of my experimentation code out because none of my experimenting worked.
public class MyScrollWheel extends Container<ScrollPane> {
private ScrollPane scrollPane;
private Image image;
private int scrollOffset;
public MyScrollWheel(){
Texture texture = new Texture(Gdx.files.internal("internal/scrollwheel.png"));
image = new Image(texture);
scrollOffset = (int)(image.getWidth()/14);
scrollPane = new ScrollPane(image);
scrollPane.setOverscroll(false, false);
setActor(scrollPane);
size(image.getWidth()-(scrollOffset*2), image.getHeight());
scrollPane.setScrollX(scrollOffset); // << this doesn't scroll
scrollPane.updateVisualScroll();
}
}

Well, I hopefully managed to get something you can build upon. What I simply did was extending actor and have it accept a Texture so I could use Texture.wrap and have it draw with SpriteBatch.draw(). I am able to keep scrolling it now and based on the scroll delta you can figure out how far it has been scrolled. I don't see any need to reset the wheel but if you really want to you can just do wheel.setScroll(0);.
One limitation is that it is not a Drawable so it cannot be scaled like a NinePatch. You have to give it a plain wheel texture draw it the size you want it to spear, you can add normal scaling however and keep aspect ratio manually. Then add the sides to it and perhaps overlay a gradient on those to create depth.
ScrollWheel:
public class ScrollWheel extends Actor {
Texture wheelTexture;
private int scroll = 0;
public int getScroll() {
return scroll;
}
public void setScroll(int scroll) {
this.scroll = scroll;
}
public ScrollWheel(Texture texture)
{
wheelTexture = texture;
wheelTexture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.ClampToEdge);
setWidth(texture.getWidth());
setHeight(texture.getHeight());
}
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
batch.draw(wheelTexture, getX(), getY(), scroll, 0,
wheelTexture.getWidth(), wheelTexture.getHeight());
}
}
usage in a Screen:
public class TestScreen implements Screen {
Stage stage;
ScrollWheel wheel;
public TestScreen() {
stage = new Stage();
Table t = new Table();
t.setFillParent(true);
stage.addActor(t);
wheel = new ScrollWheel(new Texture("hud/wheel_part.png"));
wheel.addListener(new DragListener() {
#Override
public void drag(InputEvent event, float x, float y, int pointer) {
super.drag(event, x, y, pointer);
wheel.setScroll(wheel.getScroll() + (int)getDeltaX());
}
});
t.add(wheel);
Gdx.input.setInputProcessor(stage);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(.3f, .36f, .42f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
}
//...Other mandatory screen methods...
}
So just create a wheel texture that is tillable and include that with the ScrollWheel constructor. It will draw the wheel in the center of the screen if you use this exact code.
The scroll variable essentially holds the amount of scroll so if you you want limit this between 0 and 100 you would just add this functionality in setScroll().
if (scroll > 100) scroll = 100;
else if (scroll < 0) scroll = 0;
You could then add a step to it. So if you want to rotate a image with the slider you could set the rotation by scroll * 3,6f or scroll * (maxScroll / maxStep)
I really liked the way this turned out, I will be using this for my slider in the future :D. I have extended and altered it a bit already and you can see my implementation here: https://youtu.be/RNLk5B-VfYg

Expanding on Menno Gouw's scroll wheel, I've added some more features:
Fling support with setting for fling time
Precision setting to adjust sensitivity of the wheel
Takes a Drawable
Compatible for use inside of a ScrollPane
NOTE: For my purposes I have it take in a Label in the constructor, but this can easily be changed if you don't want it tied to a Label.
Here is a video I recorded on phone demoing the scroll wheel.
https://www.youtube.com/watch?v=RwVrez4BZsY&feature=youtu.be
- EDIT 1: Layout bugs have now been fixed (hopefully). It now updates its position when moved in a ScrollPane and the Drawables are clipped to the border of the Actor.
- EDIT 2: Added support for a stationary drawable for shading and a method to change the wheel's direction (setRightPositiveDirection()).
public class ScrollWheel extends Actor {
private Drawable wheelDrawable, wheelShading;
private Label label;
private int unscaledScrollValueX=0, scrollValueX=0;
private boolean isNotEdge;
private int precision=40;
private int direction=1;
private int minValue=Integer.MIN_VALUE, maxValue=Integer.MAX_VALUE;
// MANUAL SCROLL
private int separator;
private int wheelWidth;
// FLING
private float flingTimer, flingTime=1f;
private float velocityX;
public ScrollWheel(Drawable wheelDrawable, Drawable wheelShading, Label label) {
this.wheelDrawable = wheelDrawable;
this.wheelShading = wheelShading;
this.label = label;
wheelWidth = (int)wheelDrawable.getMinWidth();
separator = wheelWidth;
setWidth(wheelDrawable.getMinWidth());
setHeight(wheelDrawable.getMinHeight());
// stops ScrollPane from overriding input events
InputListener stopTouchDown = new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
event.stop();
return false;
}
};
addListener(stopTouchDown);
ActorGestureListener flickScrollListener = new ActorGestureListener() {
public void pan (InputEvent event, float x, float y, float deltaX, float deltaY) {
updateScroll(deltaX);
}
public void fling (InputEvent event, float x, float y, int button) {
if (Math.abs(x) > 150) {
flingTimer = flingTime;
velocityX = x;
}
}
public boolean handle (Event event) {
if (super.handle(event)) {
if (((InputEvent)event).getType() == InputEvent.Type.touchDown) flingTimer = 0;
return true;
}
return false;
}
};
addListener(flickScrollListener);
}
private void updateScroll(float delta){
unscaledScrollValueX += (delta * direction);
scrollValueX = (int)(unscaledScrollValueX / precision);
isNotEdge = true;
if (scrollValueX <= minValue){
scrollValueX = minValue;
unscaledScrollValueX = minValue * precision;
isNotEdge = false;
}
else if (scrollValueX >= maxValue){
scrollValueX = maxValue;
unscaledScrollValueX = maxValue * precision;
isNotEdge = false;
}
if (isNotEdge){
separator += delta;
if (separator <= 0){
separator = wheelWidth;
}
else if (separator >= wheelWidth) {
separator = 0;
}
}
updateLabel();
}
private void updateLabel(){
label.setText("" + scrollValueX);
}
public void setMinValue(int minValue){ this.minValue = minValue; }
public void setMinValueToNone(){ minValue=Integer.MIN_VALUE; }
public void setMaxValue(int maxValue){ this.maxValue = maxValue; }
public void setMaxValueToNone(){ minValue=Integer.MAX_VALUE; }
public void setFlingTime(float flingTime){ this.flingTime = flingTime; }
public void setPrecision(int precision){ this.precision = precision; }
public void setRightPositiveDirection(boolean rightPositive){ direction = (rightPositive) ? 1 : -1; }
#Override
public void act(float delta){
super.act(delta);
boolean animating = false;
if (flingTimer > 0) {
float alpha = flingTimer / flingTime;
updateScroll(velocityX * alpha * delta);
flingTimer -= delta;
if (flingTimer <= 0) {
velocityX = 0;
}
animating = true;
}
if (animating) {
Stage stage = getStage();
if (stage != null && stage.getActionsRequestRendering()){
Gdx.graphics.requestRendering();
}
}
}
#Override
public void draw(Batch batch, float parentAlpha){
super.draw(batch, parentAlpha);
batch.flush();
if (clipBegin(getX(), getY(), getWidth(), getHeight())){
wheelDrawable.draw(batch, getX() + separator - wheelWidth, getY(), wheelDrawable.getMinWidth(), wheelDrawable.getMinHeight());
wheelDrawable.draw(batch, getX() + separator, getY(), wheelDrawable.getMinWidth(), wheelDrawable.getMinHeight());
wheelShading.draw(batch, getX(), getY(), wheelShading.getMinWidth(), wheelShading.getMinHeight());
batch.flush();
clipEnd();
}
}
}

Related

Libgdx animation doesn't play or loop

I made a game in which a turtle had to collect StarFish but when I added walking animation it doesn't work. What happens is it only shows up the first frame and the whole animation doesn't play and I get no errors.
And I'm using diffrent images to load animation
Here is my animation method-
// used to load animation from multiple files
public Animation loadAnimationFromFiles(String[] fileNames, float frameDuration, boolean loop)
{
int fileCount = fileNames.length;
Array<TextureRegion> textureArray = new Array<TextureRegion>();
for (int n = 0; n < fileCount; n++)
{
String fileName = fileNames[n];
Texture texture = new Texture( Gdx.files.internal(fileName) );
texture.setFilter( TextureFilter.Linear, TextureFilter.Linear );
textureArray.add( new TextureRegion( texture ) );
}
Animation anim = new Animation(frameDuration, textureArray);
if (loop) {
//setAnimation(anim);
System.out.println("animation run");
anim.setPlayMode(Animation.PlayMode.LOOP);
}
else {
anim.setPlayMode(Animation.PlayMode.NORMAL);
}
if (animation == null) {
System.out.println("animation null");
setAnimation(anim);
}
return anim;
}
And here is my turtle class where I used animation-
public class Turtle extends BaseActor
{
public Turtle(float x, float y, Stage s)
{
super(x, y, s);
String[] fileNames = {
"turtle2.png",
"turtle.png",
};
loadAnimationFromFiles(fileNames, 0.1f, true);
}
public void act(float dt)
{
super.act(dt);
if (Gdx.input.isKeyPressed(Input.Keys.LEFT))
this.moveBy(-5,0);
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT))
this.moveBy(5,0);
if (Gdx.input.isKeyPressed(Input.Keys.UP))
this.moveBy(0,5);
if (Gdx.input.isKeyPressed(Input.Keys.DOWN))
this.moveBy(0,-5);
}
}
You just created the animation, but never used it. To make use of the animation you need to get the textures from it, by measuring the delta time, that passed.
Your turtle class should look more like this:
public class Turtle extends BaseActor
{
private Animation<TextureRegion> animation;//store the animation in a field to use it
private float time;//use a timer for the animation to be played
public Turtle(float x, float y, Stage s)
{
super(x, y, s);
String[] fileNames = {
"turtle2.png",
"turtle.png",
};
//store the animation to the field instead of just creating it
animation = loadAnimationFromFiles(fileNames, 0.1f, true);
//set the animations timer
time = 0;
}
public void act(float dt)
{
//increase the time since the animation was started by the delta time
time += dt;
//tell the animation how much time passed, so it can give you the current animation texture
TextureRegion texture = animation.getKeyFrame(time);
//TODO draw texture
//I assume the super.act call also draws a texture; that should be deleted to not draw over the already created texture
super.act(dt);
if (Gdx.input.isKeyPressed(Input.Keys.LEFT))
this.moveBy(-5,0);
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT))
this.moveBy(5,0);
if (Gdx.input.isKeyPressed(Input.Keys.UP))
this.moveBy(0,5);
if (Gdx.input.isKeyPressed(Input.Keys.DOWN))
this.moveBy(0,-5);
}
}

Button not responding after a few clicks lib-gdx

I cant seem to find an answer to this. Why does my start button freeze after a certain amount of clicks(3)? It works for the first 3 clicks and then decides to stop working. I can still see that the screen is responding(the button becomes red when clicked), but the text on it doesn't change. It's like the click listener stopped responding.
public class MainMenu implements Screen{
private Game game;
private Stage stage;
private TextButton Start_btn;
private TextButton LocalWifi_btn;
private TextButton Internet_btn;
private TextButton Settings_btn;
private boolean Start_clicked = false;
private boolean LocalWifi_clicked = false;
private boolean Internet_clicked = false;
private boolean Settings_clicked = false;
public MainMenu(Game g){
game = g; //The Wasteland
stage = new Stage(new ExtendViewport(Gdx.graphics.getWidth(),
Gdx.graphics.getHeight())); //create a new stage with viewport to draw 2d stuff on
Gdx.input.setInputProcessor(stage); //all input set to stage
Skin skin = new Skin(Gdx.files.internal("gui/uiskin.json"), new TextureAtlas(Gdx.files.internal("gui/uiskin.atlas"))); //need this before you can make a gui
Start_btn = new TextButton("" + Start_clicked, skin);
Start_btn.setPosition(500, 500);
Start_btn.setSize(200, 200);
Start_btn.getLabel().setFontScale(10, 10); //change text size
Start_btn.addListener(new ClickListener(){
#Override
public void touchUp(InputEvent e, float x, float y, int point, int button){
onStartClicked();
}
});
stage.addActor(Start_btn);
}
private void onStartClicked(){
if(!Start_clicked){
Start_clicked = true;
Start_btn.setText("" + Start_clicked);
Gdx.app.log("Button", "" + Start_clicked);
}
else{
Start_clicked = false;
Start_btn.setText("" + Start_clicked);
Gdx.app.log("Button", "" + Start_clicked);
}
}
#Override
public void render(float delta) {
//this has to be before anything or else it will be drawn on top of everything else
Gdx.gl.glClearColor(0, 0, 0, 1); //set background color
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); //clears the screen
stage.act(delta); //send ammount of time since last render call, tells it to keep a steady fps
stage.draw();
}
#Override
public void resize(int width, int height) {
// use true here to center the camera
// that's what you probably want in case of a UI
stage.getViewport().update(width, height, true);
}
}
What am I doing wrong?!?!?!
Don't override touchUp() without calling super.touchUp(), because its messing up the functionality of ClickListener. But that's not what you want to override anyway. You should override clicked() so it only triggers if you release the click while still over the button. Or better yet, use a ChangeListener. Buttons already have a ClickListener built in that fires a change event when the button is clicked. Adding another ClickListener is redundant when you can just use a ChangeListener.

LibGDX - How to spawn objects at a certain distance from each other?

So I'm trying to create a game and it's my first time. My game is a 2D side scroller and is about the player in space avoiding the incoming meteors. I have successfully managed to get the meteors spawning randomly on the x and y axis off screen and re position once it has gone pass the screen.
But the problem I face now is sometimes the spawn of the meteors will clump together which I don't want. How do I get the meteors to spawn at a certain distance from each other so they don't clump together. I couldn't find any good tutorials or if anyone can point me to the right direction. Below are my codes so far.
Meteor Class
public class Meteors {
private Texture bigMeteor;
private Vector2 posBigMeteor;
private Random yrand;
//Constructor
public Meteors(float x){
bigMeteor = new Texture("meteor.png");
yrand = new Random();
//Spawn location of meteor
posBigMeteor = new Vector2(x, yrand.nextInt(AstroDemo.HEIGHT/2 - bigMeteor.getHeight()));
}
public Texture getBigMeteor() {
return bigMeteor;
}
public Vector2 getPosBigMeteor() {
return posBigMeteor;
}
//Reposition the meteors
public void reposition(float x){
posBigMeteor.set(x, yrand.nextInt(AstroDemo.HEIGHT/2 - bigMeteor.getHeight()));
}
}
PlayState Class
public class PlayState extends State {
//Total meteor count on screen
private static final int METEOR_COUNT = 8;
private Naught naught;
private Texture bg;
private Random xrand;
private Array <Meteors> meteors;
public PlayState(GameStateManager gsm) {
super(gsm);
//Starting co-ordinates of main character (Naught)
naught = new Naught(50, 100);
//Setting viewport of the camera
cam.setToOrtho(false, AstroDemo.WIDTH/2, AstroDemo.HEIGHT/2);
bg = new Texture("bg.png");
xrand = new Random();
meteors = new Array <Meteors>();
//Spawn meteors randomly off screen
for (int i = 1; i <= METEOR_COUNT; i++){
meteors.add(new Meteors(AstroDemo.WIDTH/2 + (xrand.nextInt(300))));
}
}
#Override
protected void handleInput() {
//If screen/mouse is held
if(Gdx.input.isTouched()){
//Main Character jumps/flys
naught.jump();
}
}
#Override
public void update(float dt) {
handleInput();
naught.update(dt);
//If meteors are left side of the screen, re-position to the right side of the screen
for(Meteors meteor : meteors){
if (cam.position.x - (cam.viewportWidth/2) > meteor.getPosBigMeteor().x + meteor.getBigMeteor().getWidth()){
meteor.reposition(meteor.getPosBigMeteor().x + (AstroDemo.WIDTH/2 + 20 + (xrand.nextInt(300))));
}
}
cam.position.x = naught.getPosition().x + 80;
cam.update();
}
#Override
public void render(SpriteBatch sb) {
//Adjust the spritebatch for co-ordinate system in relation to camera
sb.setProjectionMatrix(cam.combined);
sb.begin();
//Draw background where the camera is
sb.draw(bg, cam.position.x - (cam.viewportWidth/2), 0);
sb.draw(naught.getTexture(), naught.getPosition().x, naught.getPosition().y);
for (Meteors meteor : meteors) {
sb.draw(meteor.getBigMeteor(), meteor.getPosBigMeteor().x, meteor.getPosBigMeteor().y);
}
sb.end();
}
#Override
public void dispose() {
}
}
create a array of predefined value for your y position and then get value randomly from that array.
or
Divide height into sub portion then get random value from that portion so that each random value not collide with other value.

LibGdx label background with 9patch

So i've come across this problem that i simply can't manage to sort out.
I'm making a game with the help of LibGdx and am trying to create a chat bubble functionality. The problem is, when i try to change the background of the label style to a 9patch drawable, it doesn't scale it well, or at all?
public class ChatBubble
{
private Label textLabel;
private BitmapFont font;
private Label.LabelStyle lStyle;
private int scaledWidth = 0;
private int scaledHeight = 0;
private Timer.Task currentTask;
private Texture bkg;
public ChatBubble()
{
font = new BitmapFont();
font.setColor(Color.BLACK);
bkg = new Texture("data/ui/chatb.9.png");
NinePatch np = new NinePatch(bkg,11,11,9,10);
NinePatchDrawable npd = new NinePatchDrawable(np);
lStyle = new Label.LabelStyle(font,font.getColor());
lStyle.background = npd;
textLabel = new Label("",lStyle);
textLabel.setVisible(false);
textLabel.setAlignment(Align.center);
currentTask = new Timer.Task() {
#Override
public void run() {
textLabel.setVisible(false);
}};
}
public void show(String text, float duration)
{
if(currentTask.isScheduled())currentTask.cancel();
textLabel.setText(text);
textLabel.setVisible(true);
scaledHeight = (int)textLabel.getPrefHeight();
scaledWidth = (int)textLabel.getWidth()/2;
Timer.schedule(currentTask,duration);
}
public void show(String text)
{
if(currentTask.isScheduled())currentTask.cancel();
textLabel.setText(text);
textLabel.setVisible(true);
scaledHeight = (int)textLabel.getPrefHeight();
scaledWidth = (int)textLabel.getWidth()/2;
Timer.schedule(currentTask,(float)(text.length()*0.1));
}
public void draw(SpriteBatch batch, float x, float y)
{
if(!textLabel.isVisible())return;
textLabel.setPosition(x - scaledWidth, y + scaledHeight);
batch.begin();
textLabel.draw(batch, 1);
batch.end();
}
}
How it looks ingame:
How the 9batch looks:
Any help would be appreciated!
Update:
I've found out that my 9patch scales ok, the problem being in label not updating it's size when setText() is called, thus having it width and height 0 since constructor was "".. calling layout() on label doesn't solve this either.
Call .pack() on the label after .setText() to tell it to size itself to its text (plus whatever padding there is in the background drawable). You don't need to call layout() since that's handled automatically.
I'm not sure the exact reason you have to manually call pack(), but this is generally the case with Widgets that you are not children of a WidgetGroup subclass (i.e. Table, VerticalGroup, etc.).

Java Translucent Selection Box

For custom rendering, I've created a class that extends JPanel and overrides the paintComponent method. In the custom paintComponent I rendering multiple shape objects held in a array. What I would like to add is the ability to drag and select 1 or more of the shapes. While dragging I would like to show a translucent rectangle defining the selection region akin to what is seen in Windows Explorer. Can any provide a starting point for accomplishing this?
Thanks.
I saw an interesting way of doing this in JFreeChart's source code. You can draw a marquee over a section of the chart, and when you release the mouse the chart zooms in on the selected are. Re-rending the chart is expensive and unfortunately JFreeChart doesn't support partial paints of a chart. So to draw the marquee they do some sort of bitwise operation to the colors of the component, in a reversible fashion. Every time the mouse moves while selecting a marquee, you reverse the previous bitwise operation on the old coordinates, then redo it on the new coordinates.
Take a look at ChartPanel.java in JFreeChart
private void drawZoomRectangle(Graphics2D g2) {
// Set XOR mode to draw the zoom rectangle
g2.setXORMode(Color.gray);
if (this.zoomRectangle != null) {
if (this.fillZoomRectangle) {
g2.fill(this.zoomRectangle);
}
else {
g2.draw(this.zoomRectangle);
}
}
// Reset to the default 'overwrite' mode
g2.setPaintMode();
}
You could use JXLayer. Span it across the whole form and do the painting in a custom LayerUI.
All,
Thanks for the suggestions. Ended up resolving this by adapting some the code used in this rather clever demo. http://forums.sun.com/thread.jspa?threadID=5299064&start=19
public class ExamplePanel extends JPanel
{
Rectangle2D.Double selectionRect;
Point mouseDown, mouseHere;
...
protected void paintComponent(Graphics g)
{
AlphaComposite ta = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f);
g2d.setComposite(ta);
g2d.setColor(Color.BLUE);
g2d.fill(selectionRect);
g2d.setComposite(AlphaComposite.SrcOver);
g2d.setColor(Color.BLACK);
g2d.draw(selectionRect);
}
}
public class ExammpleMouseListener extends MouseAdapter
{
#Override
public void mousePressed(MouseEvent e)
{
super.mousePressed(e);
// store the mouse down location
pnl.mouseDown = e.getPoint();
}
/**
* #see java.awt.event.MouseAdapter#mouseDragged(java.awt.event.MouseEvent)
*/
#Override
public void mouseDragged(MouseEvent e)
{
super.mouseDragged(e);
// check for left mouse button
if ((e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) == 0)
{
return;
}
// store the current location
pnl.mouseHere = e.getPoint();
// calculate the size of the selection rectangle
double downX = pnl.mouseDown.getX();
double downY = pnl.mouseDown.getY();
double hereX = pnl.mouseHere.getX();
double hereY = pnl.mouseHere.getY();
double l = Math.min(downX, hereX);
double t = Math.min(downY, hereY);
double w = Math.abs(downX - hereX);
double h = Math.abs(downY - hereY);
pnl.selectionRect = new Rectangle2D.Double(l, t, w, h);
// queue a repaint of the panel
pnl.repaint();
}
#Override
public void mouseReleased(MouseEvent e)
{
super.mouseReleased(e);
// clear the selection rectangle
pnl.selectionRect = null;
// queue a repaint of the panel
pnl.repaint();
}
}
}
Sure, here's an simple example with methods for creating and moving the shape.
class MyShape implements Shape {
private Shape shape;
public void createShape(Point p1, Point p2, ShapeType t) {
switch(t) {
case RECTANGLE: {
shape = new Rectangle2D.Double(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y);
break;
}
... (other shapes)
}
}
public void moveShape(Point lastPoint, Point newPoint, ShapeType t) {
int xOffset = newPoint.x - lastPoint.x;
int yOffset = newPoint.y - lastPoint.y;
switch(t) {
case RECTANGLE: {
double x1 = shape.getBounds().getX() + xOffset;
double y1 = shape.getBounds().getY() + yOffset;
double w = shape.getBounds().getWidth();
double h = shape.getBounds().getHeight();
shape = new Rectangle2D.Double(x1, y1, w, h);
break;
}
... (other shapes)
}
}
}
For some components ( I don't know if this apply to your components while being dragged ) you can set the background and use a "transparent color"
The Color class does implements Transparency.
To use it you may specify the alpha value in the Color constructor.
For instance this is a semi transparent black background:
// 0: totally transparent
// 255: totally opaque,
// 192 semy transparent.
this.setBackground(new Color( 0, 0, 0, 192 ));
See the [constructor][1]
Again, I'm not sure if this applies to you. Give it a try
[1]: http://java.sun.com/javase/6/docs/api/java/awt/Color.html#Color(int, int, int, int)

Categories