Im making an app which has a listener on incoming calls and then adds fields til the phonescreen..
However i cannot seem to really control the width of either labelfields or the PhoneScreenVerticalManager i use.
If i try to set a border or background on the PhoneScreenVerticalManager nothing happens at all.
It also seems like USE_ALL_WIDTH in the labelfield constructor doesn't change anything.
And getting the labelfields to left align i also couldn't get to work (tried DrawStyle.Left in the labelfield constructor).
here is my code:
public Incoming(int callId) {
this.callId = callId;
PhoneCall call = Phone.getCall(callId);
String number = call.getPhoneNumber();
Vector contact = ContactUtil.getContactByPhone(number);
screenModel = new ScreenModel(callId);
phoneScreenPortrait = screenModel.getPhoneScreen(PhoneScreen.PORTRAIT, PhoneScreen.INCOMING);
final XYRect rect = screenModel.getDimensions(PhoneScreen.PORTRAIT, PhoneScreen.INCOMING);
PhoneScreenVerticalManager manager = new PhoneScreenVerticalManager()
{
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.setBackgroundColor(Color.WHITE);
g.clear();
super.paint(g);
}
protected void sublayout(int width, int height)
{
super.sublayout(rect.width, height);
super.setExtent(rect.width, height);
}
};
manager.setBackground(BackgroundFactory.createSolidBackground(Color.RED));
manager.setBorder(BorderFactory.createSimpleBorder(new XYEdges(BORDER_PADDING, BORDER_PADDING, BORDER_PADDING, BORDER_PADDING), Border.STYLE_SOLID));
String s = res.getString(FOUND_IN_CONTACTS);
LabelField header = new LabelField(s, LabelField.USE_ALL_WIDTH)
{
protected void layout(int width, int height)
{
super.layout(rect.width, height);
setExtent(rect.width, height);
}
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.setBackgroundColor(Color.WHITE);
g.clear();
super.paint(g);
}
};
header.setBackground(BackgroundFactory.createSolidBackground(Color.WHITE));
manager.add(header);
LabelField label = new LabelField(contact.firstElement().toString(), LabelField.USE_ALL_WIDTH)
{
protected void layout(int width, int height)
{
super.layout(rect.width, height);
setExtent(rect.width, height);
}
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.setBackgroundColor(Color.WHITE);
g.clear();
super.paint(g);
}
};
label.setBackground(BackgroundFactory.createSolidBackground(Color.WHITE));
manager.add(label);
phoneScreenPortrait.add(manager);
screenModel.sendAllDataToScreen();
}
Any ideas would be greatly appreciated!ยจ
Thanks
though the phonescreen managers are derived from the field manager it doesn't support all the field manager properties.
so the solution is to set up normal field manager and then add those to the phonescreen managers
Related
I've written an app that custom draws everything inside paint() based on fixed pixel positions. Then I disabled resize of the frame so its always visible.
However, now I would like to be able to resize it but I dont want to change my drawling code. I was hoping I could grab the 300x300 square of the Graphics g object and resize it to the JFrame current size after all of my drawling code, but I have no idea what I'm doing.
Here sample code. In this I want the 100x100 square to remain in the middle, proportionate to the resized JFrame:
package DrawAndScale;
import java.awt.Color;
import java.awt.Graphics;
public class DASFrame extends javax.swing.JFrame {
public DASFrame() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
this.setSize(300, 300);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new DASFrame().setVisible(true);
}
});
}
#Override
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.fill3DRect(100, 100, 100, 100, true);
}
}
Thanks.
Assuming you rename your method that paints for 300x300 as paint300, define a buffered image:
#Override public void paint(Graphics g) {
Image bufferImage = createImage(300, 300); // empty image
paint300(bufferImage.getGraphics()); // fill the image
g.drawImage(bufferImage, 0, 0, null); // send the image to graphics device
}
Above is when you want to draw at full size (300x300).
If your window is resized:
#Override public void paint(Graphics g) {
Image bufferImage = createImage(300, 300);
paint300(bufferImage.getGraphics());
int width = getWidth();
int height = getHeight();
CropImageFilter crop =
new CropImageFilter((300 - width)/2, (300 - height)/2 , width, height);
FilteredImageSource fis = new FilteredImageSource(bufferImage, crop);
Image croppedImage = createImage(fis);
g.drawImage(croppedImage, 0, 0, null);
}
The new classes are from from java.awt.image.*.
I didn't test this code. It's just to send you in the right direction.
if you want to painting Custom paint then look for JLabel or JPanel and including Icon/ImageIcon inside, simple example about that
import java.awt.*;
import javax.swing.*;
public class MainComponentPaint extends JFrame {
private static final long serialVersionUID = 1L;
public MainComponentPaint() {
setTitle("Customize Preffered Size Test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void display() {
add(new CustomComponent());
pack();
setMinimumSize(getSize());
setPreferredSize(getSize());
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
setVisible(true);
}
});
}
public static void main(String[] args) {
MainComponentPaint main = new MainComponentPaint();
main.display();
}
}
class CustomComponent extends JComponent {
private static final long serialVersionUID = 1L;
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
for (int i = 0; i < Math.max(w, h); i += 20) {
g.drawLine(i, 0, i, h);
g.drawLine(0, i, w, i);
}
}
}
Not an expert, but you could just scale the Graphics2D object (the passed Graphics is in fact a Graphics2D instance), where the x and y ratios are the ratios of the fixed size you chose to draw and the actual size of the frame.
See http://download.oracle.com/javase/6/docs/api/java/awt/Graphics2D.html#scale%28double,%20double%29
You could do this with some math.
public void paint(Graphics g){
int height = 100;
int width = 100;
int x = (this.getWidth() / 2) - (width / 2);
int y = (this.getHeight() / 2) - (height / 2);
g.setColor(Color.BLACK);
g.fill3DRect(x, y, width, height, true);
}
Or if you wanted to keep the width and height of the box with the same proportion, use int width = this.getWidth() / 3; and int height = this.getHeight() / 3.
The other option is to use Graphics2D.scale(), as JB pointed out, the passed Graphics object is actually a Graphics2D object.
I want to put an image (visualization of an audio) behind the JSlider which represents the audioplayer, the process of playing.
First I tried to overwrite the paint-method of the Slider
public void paintComponent(Graphics g) {
// Draw the previously loaded image to Component
g.drawImage(img, 0, -100, null);
super.paintComponent(g);
}
this worked, but the image is higher than the slider, so my next try was a JLayeredPane, where I put the JSlider above a JLabel with the image. Looks good for the first moment. But I mentioned that I need the image behind the track of the slider, not the whole slider. There is space to the left and right. Can anybody tell me a way how to calculate this space? Or the width and offset of the track to the border of the slider? This should run under Windows and MacOs, so different LookAndFeels, so I think hard coded values will not work.
Example Slider with background image
Thankyou.
My solution for this Problem is now to overwrite the SliderUI. So this is a very special component, so it's nonrelevant that it looks the same on all LookAndFeels.
It supports also jumping directly to mouse position, which is different to BasicSliderUI.
/**
*
* Custom SliderUI for AudioPlayer with audioimage in background
*/
public class AudioSliderUI extends BasicSliderUI {
private BasicStroke stroke = new BasicStroke(1f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND, 0f);
public AudioSliderUI(AudioSlider b) {
super(b);
}
#Override
public void paint(Graphics g, JComponent c) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
super.paint(g, c);
}
#Override
protected Dimension getThumbSize() {
return new Dimension(2, 200);
}
#Override
public void paintTrack(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Stroke old = g2d.getStroke();
g2d.setStroke(stroke);
g2d.setPaint(Color.WHITE);
if (slider.getOrientation() == SwingConstants.HORIZONTAL) {
g2d.drawLine(trackRect.x, trackRect.y + trackRect.height / 2,
trackRect.x + trackRect.width, trackRect.y + trackRect.height / 2);
} else {
g2d.drawLine(trackRect.x + trackRect.width / 2, trackRect.y,
trackRect.x + trackRect.width / 2, trackRect.y + trackRect.height);
}
g2d.setStroke(old);
Image img = ((AudioSlider)slider).getImage();
g2d.drawImage(img, trackRect.x, trackRect.y, trackRect.width, trackRect.height, slider);
}
#Override
public void paintThumb(Graphics g) {
Rectangle knobBounds = thumbRect;
int w = knobBounds.width;
int h = 100;
int newStarty = knobBounds.height/2- h/2;
g.translate(knobBounds.x, knobBounds.y);
// "plain" version
g.setColor(Color.YELLOW);
g.fillRect(0, newStarty, w, h);
}
#Override
protected TrackListener createTrackListener(JSlider slider) {
return new TrackListener() {
#Override
public void mousePressed(MouseEvent e) {
if (UIManager.getBoolean("Slider.onlyLeftMouseButtonDrag")
&& SwingUtilities.isLeftMouseButton(e)) {
JSlider slider = (JSlider) e.getComponent();
switch (slider.getOrientation()) {
case SwingConstants.VERTICAL:
slider.setValue(valueForYPosition(e.getY()));
break;
case SwingConstants.HORIZONTAL:
slider.setValue(valueForXPosition(e.getX()));
break;
default:
throw new IllegalArgumentException(
"orientation must be one of: VERTICAL, HORIZONTAL");
}
super.mousePressed(e); // isDragging = true;
super.mouseDragged(e);
} else {
super.mousePressed(e);
}
}
#Override
public boolean shouldScroll(int direction) {
return false;
}
};
}
}
Matching Slider:
public class AudioSlider extends JSlider {
private Image img;
public AudioSlider() {
setOpaque(false);
}
/**
* #return the img
*/
public Image getImage() {
return img;
}
public void setImage(Image img) {
this.img = img;
}
}
Works for me, maybe covers not all prospects.
I've run into a bit of a wall here. I read elsewhere while trying to fix this issue that you are never supposed to getGraphics(). The problem is, I can't use the provided Graphics context from the paint() / paintComponent() methods. I require it to only call my generate(Graphics g) function once, and I can not provide Graphics outside of the override functions.
Any tips? Trimmed for your convenience.
public class Main extends JPanel {
...
static JFrame displayFrame, inputFrame;
...
...
// Generator node list
ArrayList<Node> nodes = new ArrayList<Node>();
public static void main(String[] args) {
// Set up the frame
screenSize = Toolkit.getDefaultToolkit().getScreenSize();
displayFrame = new JFrame("City generator");
displayFrame.setSize(screenSize.width / 3, screenSize.width / 3);
displayFrame.setLocation(screenSize.width / 2 - displayFrame.getWidth()
/ 2, screenSize.height / 2 - displayFrame.getHeight() / 2);
displayFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
displayFrame.add(new Main());
// displayFrame.setUndecorated(true);
displayFrame.setBackground(Color.lightGray);
displayFrame.setVisible(true);
displayFrame.addMouseMotionListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
// Mouse movement events here
}
});
}
// Override function
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Calls multiple times
generate(g);
}
private void generate(Graphics g) {
............................
Instead of painting directly to the Graphics context, you could generate a BufferedImage image of what you want painted and paint to that instead...
private BufferedImage buffer;
public BufferedImage generate() {
if (buffer == null) {
buffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_IMAGE_ARGB);
Graphics2D g2d = buffer.createGraphics();
// Paint away...
g2d.dispose();
}
return buffer;
}
Then you would paint the result within the paintComponent method...
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Calls multiple times
BufferedImage img = generate();
g.drawImage(img, 0, 0, this);
}
As an example...
Why not just keep a boolean value to track if generate() has been called.
public boolean calledGenerate = false;
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (!calledGenerate) generate(g);
}
void generate(Graphics g) {
calledGenerate = true;
....
}
also you are calling AWT/Swing code outside of the EDT which is a bad idea.
In your main function you normally should call:
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
//build your awt/swing objects here
}
});
What does generate() do though? There is probably a better way to do it.
I have tried quite a few tutorials and I can't seem to get double buffering to work. Here is my main (the update() method is the code i tried, but I still see flickering):
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);
private Image dbImage;
private Graphics dbg;
public static Ailoid ailoid = new Ailoid();
// Initialize
public void init() {
setSize(width, height);
setBackground(Color.white);
ailoid.setLocation(new Location(100, 100));
AlienManager.registerAlien(ailoid);
}
// Paint graphics
public void paint(Graphics g) {
super.paint(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);
}
}
// Update graphics for double buffering
public void update(Graphics g) {
if (dbImage == null) {
dbImage = createImage (width, height);
dbg = dbImage.getGraphics();
}
dbg.setColor (getBackground ());
dbg.fillRect (0, 0, width, height);
dbg.setColor (getForeground());
paint (dbg);
g.drawImage (dbImage, 0, 0, this);
}
// Thread start
#Override
public void start() {
thread.start();
}
// Thread stop
#Override
public void destroy() {
thread = null;
}
// Thread run
#Override
public void run() {
while (thread != null) {
Updater.run();
repaint();
try {
// 1000 divided by fps to get frames per millisecond
Thread.sleep(1000 / fps);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
If someone could help it would be greatly appreciated!
Instead of drawing your objects one by one, draw them on an image and then tell the renderer to draw that entire image. This eliminates the flickering.
Here's an example of how you might accomplish it.
class DoubleBufferedCanvas extends Canvas {
public void update(Graphics g) {
Graphics offgc;
Image offscreen = null;
Dimension d = size();
// create the offscreen buffer and associated Graphics
offscreen = createImage(d.width, d.height);
offgc = offscreen.getGraphics();
// clear the exposed area
offgc.setColor(getBackground());
offgc.fillRect(0, 0, d.width, d.height);
offgc.setColor(getForeground());
// do normal redraw
paint(offgc);
// transfer offscreen to window
g.drawImage(offscreen, 0, 0, this);
}
}
I am creating five EditFields with corresponding label fields.
The EditFields use the full width of the screen but I need only want them to use a particular width.
try this code:-
BasicEditField bef = new BasicEditField("BBDeveloper","")
{
public int getPreferredHeight()
{
return 30;
}
public int getPreferredWidth()
{
return 100;
}
public void layout(int width, int height)
{
setExtent(getPreferredWidth(), getPreferredHeight());
super.layout(getPreferredWidth(), getPreferredHeight());
}
};
alter the getPreferredWidth() and getpreferredHeight() returning values... and see if this help you out....
set the change font bellow the rewritable methods like these:
lbDesc = new LabelField(title, LabelField.USE_ALL_WIDTH)
{
protected void paint(Graphics g)
{
//Font font = Font.getDefault().derive(Font.PLAIN,6,Ui.UNITS_pt);
//g.setFont(font);
g.setColor(Color.BLACK);
invalidate();
super.paint(g);
}
};
Font font = Font.getDefault().derive(Font.PLAIN,6,Ui.UNITS_pt);
lbDesc.setFont(font);