Applying new UI to JInternalFrame title - java

I've never done anything with UI's before and I've been tasked with getting our internal frame titles changed. We're using the Nimbus L&F and in our UI manager I've tried
UIManager.put("InternalFrameTitlePane.background", Color.RED);
just to try and get something to change. The didn't work for me and I found another post somewhere about creating a UI using the BasicInternalFrameTitlePane so I now have this code:
public class CFrameTitleUI extends BasicInternalFrameTitlePane {
public CFrameTitleUI(JInternalFrame f)
{
super(f);
}
#Override
public void paintTitleBackground(Graphics g)
{
g.setColor(Color.RED);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
But now that I have this I'm not sure what to do with it. I've tried setting the UI in the internal frame using it's setUI() method, but this is a title bar for it so I'm sure thats wrong. I next tried
UIManager.put("InternalFrameTitlePane.background", CFrameTitleUI.getClass().getName());
and
UIManager.put("InternalFrameTitlePane", CFrameTitleUI.getClass().getName());
but nothing. Do I need to tie it back to the nimbus L&F somehow? Some of the things we're setting say "nimbusSelection" etc..
Main questions are am I creating a custom UI for the internal frame titles correctly and how do I apply it, thanks.

Do you get the same?
public class InternalFrameTest extends JFrame {
public InternalFrameTest() {
JDesktopPane desktop = new JDesktopPane();
JInternalFrame frame = new JInternalFrame("AHHHH!!!!", true);
frame.setSize(300, 300);
frame.setVisible(true);
frame.setOpaque(false);
desktop.add(frame);
setContentPane(desktop);
setSize(600, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(NimbusLookAndFeel.class.getName());
} catch (ClassNotFoundException|InstantiationException
|IllegalAccessException|UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
UIManager.put("InternalFrame:InternalFrameTitlePane[Enabled].textForeground", Color.RED);
new InternalFrameTest();
}
}
When I run (without setting anything to it)
System.out.println(UIManager.getColor("InternalFrame:InternalFrameTitlePane[Enabled].textForeground"));
I get
"DerivedColor(color=142,143,145 parent=nimbusDisabledText offsets=0.0,0.0,0.0,0 pColor=142,143,145"
Do you get the same?

Related

Draw in JPanel with java swing Graphics g

This is my first java project and I am trying to draw a simple rectangle on my JPanel inside my JFrame. Been trying to solve this issue with the help of the same topics on stackoverflow but still no success.
The exception I get when I run the program is java.lang.NullPointerException. From my understanding I can not draw on the JPanel itself? which is created in mainWindow.
Main:
public class Main {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GameBoard game = new GameBoard();
mainWindow view = new mainWindow(game);
mainModel model = new mainModel();
mainController cont = new mainController(model, view, game);
cont.controllerInit();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
View:
public class mainWindow{
public JFrame frame;
public JPanel panel;
GameBoard game = new GameBoard();
frame = new JFrame();
frame.getContentPane().setBackground(SystemColor.control);
frame.setBounds(100, 100, 728, 435);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(game);
frame.getContentPane().setLayout(null);
panel = new JPanel();
FlowLayout flowLayout = (FlowLayout) panel.getLayout();
panel.setBounds(166, 44, 550, 349);
frame.getContentPane().add(panel);
frame.setVisible(true);
}
Game:
public class GameBoard extends JPanel{
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLUE);
g.drawRect(200, 200, 200, 200);
}
}
Never, ever call paintComponent directly, no external source has any reason to do so. Also, what do you thing would happen if you passed it null?
You should start by having a look at Performing Custom Painting and Painting in AWT and Swing to get a better understand of how paint in Swing works.
The Swing API basically uses a delegate model, where the system delegates responsibility of the paint of each component to the component. This is achieved by the system calling the components paint method, which in-turn calls (among a few others) paintComponent.
Swing also uses a passive rendering approaching, meaning that painting occurs at the discretion of the paint system. You component is notified of the need when its paint method is called. This may occur at any time.
In order for a component to be painted, it must first be added to container which is realised on the screen (has a native peer), in most cases, this means that the component hierarchy needs to resolve to some kind of window based class, like JFrame.
So, the answer to your question is:
Read the above documentation (and get a better understanding of how the API works)
Add your GameBoard to a container which can be resolved to a window based class
Never call paint or paintComponent directly
Reflection....
private mainWindow view;
private mainModel model;
public GameBoard(mainModel m, mainWindow v)
{
view = v;
model = m;
}
To me, this makes no sense. There is no reasonable reason why GameBoard needs a reference to mainWindow. GameBoard is, in of itself, a "view". If anything, the only thing you "should" be passing to GameBoard (assuming you're trying to use a MVC) is a controller

Java repaint() doesn't call paintComponent() for drawing image

I have read a lot of answers about this problem but I can't manage to find my error even on a simple code. Here is the problem : I'd like to draw an Image in a JLabel which is in a JPanel, but the paintComponent() method of the JLabel isn't called.
Here is the code :
The ImagePainter class should draw an image
public class ImagePainter extends JLabel{
private Image image;
public ImagePainter(){
try {
image = ImageIO.read(new File("src/testgui/image.png"));
} catch (IOException exception) {
exception.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
System.out.println("in paintComponent");
}
}
Here is a standard JFrame. I took care to add the JPanel to the contentPane
public class Display extends JFrame{
public Display(){
JPanel jp = new JPanel();
ImagePainter i = new ImagePainter();
getContentPane().add(jp);
jp.add(i);
jp.repaint();
setSize(800, 800);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
And finally the main. I instanciate Display on the EDT like everyone tell to do :
public class Main {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
Display d = new Display();
}
});
}
}
Finally, I observed that if I directly add the ImagePainter to the contentPane, the image is drawn correctly. It's probably a stupid error but I spend literally hours trying to find it and really can't see it. Thank you in advance !
The label does not account for the preferred size of the image when the image is custom painted! The panel by default has a flow layout. A flow layout does not stretch components to fit. So that label would have size of 0 x 0 pixels. You can confirm that by adding a visible border to the label.
But given the image is displayed in a label, why not just set the image as the icon of the label?
Also, the jp.repaint() statement in the Display constructor is useless, since you have not yet set the frame visible.

JFrame - Draw graphics over a transparent background?

I am trying to make an undecorated transparent JFrame, and then paint some graphics over it. If I extend JFrame, set undecorated to true, and override paint with, I can make a transparent JFrame. Like this:
public class MainFrame extends JFrame {
public static void main(String[] args) throws Exception {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainFrame frame = new MainFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public MainFrame() {
setTitle("ASDF");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setUndecorated(true);
setBounds(0, 0, 200, 200);
}
public void paint(Graphics g){
g.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 20));
g.drawString("ASDF", 100, 100);
}
}
The problem is that when I try drawing something on it, I can't clear what is drawn for another repaint. Like in this example, the text retains the background that was there when it was drawn. So if I move a a window behind the frame, it looks weird, because the frame itself has the old background. I tried AlphaComposite.Clear, but that only made a black background. What can I do?
If I extend JFrame, set undecorated to true, and override paint with, I can make a transparent JFrame.
I don't think so. You just paint without caring about the background, which is quickly lost. If you want to know how to make transparent windows in java use Stackoverflow: search for [java] transparent window. This should help you creating such a window, but this is quite a complicated task: Transparent Window

How to put a 800x600 image in a jLabel without having to scroll to see the whole image

i tried ways like getScaledInstance but all does not work. i could not find any solutions online either. the code that i am currently using is:
public class ShowImage_1 extends Panel {
BufferedImage image;
public ShowImage_1() {
try {
File input = new File("C:/Lighthouse.jpg");
image = ImageIO.read(input);
image.getGraphics().drawImage(image, 0, 0, 400, 400, null);
} catch (IOException ie) {
System.out.println("Error:" + ie.getMessage());
}
}
public void paint(Graphics g) {
g.drawImage(image, 0, 0, null);
}
static public void main(String args[]) throws Exception {
JFrame frame = new JFrame("Display image");
Panel panel = new ShowImage_1();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
it does not show the full image on the panel. any idea on how to go about doing it?
i want to achieve this effect: http://img209.imageshack.us/i/77894822.png/
but what i get now is this: http://img600.imageshack.us/i/19267006.png/
any other code i can use to get that?
Make the panel large enough to hold the image.. This may solve your problem
Add the image to a JLabel. Add the label to the frame. Then use:
frame.pack();
NOT
frame.setSize(800, 600);
If you need more help post your SSCCE demonstrating the problem.

How can I make my GUI Frame larger?

The problem is, I am unable to make it a dimension with 800x600. In other words, when I run the program, the frame is so small that I can not do anything with it.
How can I make the frame larger?
I have set the preferred size already ans set the canvas bounds.
Then what is the problem?
public class GameCanvas extends Canvas
{
private BufferStrategy buffer = null;
public GameCanvas()
{
setBounds(0, 0, 800, 600);
setIgnoreRepaint(true);
addKeyListener(new KeyInputHandler());
requestFocus();
}
public void addNotify()
{
super.addNotify();
this.createBufferStrategy(2);
buffer = this.getBufferStrategy();
setBounds(0, 0, 800, 600);
}
}
public class GameGuiFrame extends JFrame
{
private JPanel panel = new JPanel();
private GameCanvas canvas = new GameCanvas();
public GameGuiFrame()
{
this.setName("My Game");
this.pack();
this.setResizable(false);
this.setVisible(true);
panel = (JPanel) this.getContentPane();
panel.setPreferredSize(new Dimension(750,500));
panel.setLayout(null);
panel.add(canvas);
}
}
public class GameManager
{
public static void runGameLoop()
{
GameGuiFrame container = new GameGuiFrame();
container.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
}
}
public class Main
{
public static void main(String [] args)
{
GameManager.runGameLoop();
}
}
Try packing the Frame after you set the preferred size of the content pane.
Not related to your question but based on the code you posted it looks like you've copied some old AWT code and are trying to use it in a Swing application.
I would suggest you only use Swing components. There is no need to use a Canvas with a BufferStrategy. Just use a JPanel it is double buffered by default. The code snippet you copied is old and that is not the way it is done in Swing.
Don't use a null layout. Swing was designed to be using with layout managers. Then the pack() method will be able to do its job properly.
There is no need to use a WindowListener to close the frame. These days people just use:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Also, the frame should be made visible AFTER components have been added to the frame.
Generally you should be use Key Bindings, not a KeyListener to listen for key events in a Swing application.
I suggest you look at the Swing tutorial for more information about the above concepts.
You call to pack() will set the frame (and components within it) to their preferred size. However, you haven't specified a preferred size. I would suggest removing your two calls to setBounds() and calling setBounds() within the main method instead of pack().

Categories