I'm trying to implement 2D text rendering into my LWJGL game and have searched everywhere for a working solution, but keep getting the same error. I am currently trying to follow this tutorial. Here is the error:
Exception in thread "main" java.lang.IllegalStateException: Function is not supported
at org.lwjgl.BufferChecks.checkFunctionAddress(BufferChecks.java:58)
at org.lwjgl.opengl.GL11.glColor4f(GL11.java:893)
at org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer.glColor4f(ImmediateModeOGLRenderer.java:124)
at org.newdawn.slick.Color.bind(Color.java:182)
at org.newdawn.slick.TrueTypeFont.drawString(TrueTypeFont.java:363)
at org.newdawn.slick.TrueTypeFont.drawString(TrueTypeFont.java:355)
at guis.Gui.drawString(Gui.java:23)
at engineTester.MainGameLoop.main(MainGameLoop.java:110)
and here is my Gui class:
package guis;
import java.awt.Font;
import org.newdawn.slick.TrueTypeFont;
public class Gui {
private TrueTypeFont font;
private Font awtFont;
public Gui() {
this.awtFont = new Font("Times New Roman", Font.BOLD, 24);
this.font = new TrueTypeFont(awtFont, false);
}
public void drawString(int x, int y, String text) {
font.drawString(x, y, text);
}
}
Why is this error caused?
EDIT: Regarding this answer to another question: https://stackoverflow.com/a/26319508/5838494 I already did this and it does not work.
You need to set up your opengl version lower than 3.0, because functions used by TrueTypeFont have been removed in 3.x.
Or you can take a look into opengl 3.x / 4.x
Opengl3.3
if you do not have to support older opengl versions.
The problem here is probably that you do something like
public Gui theGui = new Gui();
in your main class I guess. Now, when you do this, the constructor is called and when you create your TrueTypeFont there, there is no OpenGL context yet, because the main class is also just being initialized, and hence the drawing fails because it has no OpenGL context.
You can try and change that to just a declaration like public Gui gui; and then, when you load your application, after you created the GL context, you assign the field with this.gui = new Gui();.
But I can only guess here because you do not have much code in your question. There might be other problems with this code, like incompatibility of the Slick library (Do you have the latest version, or better the version that's known to be compatible with your OpenGL version?), or similar.
Related
I am writing a Java application for image analysis which at one point opens ImageJ with
ImageJ ij = new ImageJ();
and also opens a Windows containing an ImagePlus.
Now, whenever one closes ImageJ first, the ImagePlus will not close when pushing the close button. The other way around works, however in both cases an exception is thrown after closing ImageJ:
java.lang.reflect.InvocationTargetException
at java.awt.EventQueue.invokeAndWait(EventQueue.java:1288)
at java.awt.Window.doDispose(Window.java:1209)
at java.awt.Window.dispose(Window.java:1147)
at ij.ImageJ.run(ImageJ.java:784)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: null source
at java.util.EventObject.<init>(EventObject.java:56)
at java.awt.AWTEvent.<init>(AWTEvent.java:337)
at java.awt.event.InvocationEvent.<init>(InvocationEvent.java:285)
at java.awt.event.InvocationEvent.<init>(InvocationEvent.java:174)
at sun.awt.X11.XBaseMenuWindow.dispose(XBaseMenuWindow.java:907)
...
I don't know whether it is related as it happens in both cases.
Any suggestions on how to force ImageJ to close all its windows?
The exception
This happens when using OpenJDK 7 on Linux. The exception is fixed in Java 8.
Also: note that that exception is not the actual cause of the quitting issue you are seeing.
The disposal problem
ImageJ 1.x's application disposal is a convoluted mess. (See this news post for some technical discussion.) It was really intended primarily to run as a standalone application, and is mostly tested with the exitWhenQuitting flag set to true such that the JVM shuts down upon closure of the main window. So it is not surprising that using ImageJ in a different fashion results in hanging image windows.
I have tested various workarounds—e.g.:
ij.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(final WindowEvent e) {
// dispose all image windows
for (final int id : WindowManager.getIDList()) {
final ImagePlus imp = WindowManager.getImage(id);
if (imp == null) continue;
final ImageWindow win = imp.getWindow();
if (win != null) win.dispose();
}
// dispose all other ImageJ windows
for (final Window w : WindowManager.getAllNonImageWindows()) {
w.dispose();
}
}
});
But none of them work as one might hope. It cost me weeks of development and experimentation to make quitting work as we wanted in ImageJ2, according to the news posted linked above.
Here is some code using ImageJ2 that almost behaves the way you want:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
import net.imagej.ImageJ;
public class IJDispose {
public static void main(final String... args) {
final ImageJ ij = new ImageJ();
ij.ui().showUI();
final JFrame frame = new JFrame("Hello");
final JButton b = new JButton("Close ImageJ");
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
ij.getContext().dispose();
}
});
frame.getContentPane().add(b);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
After launching it, press Shift+B to open the Blobs sample image. Then click the "Close ImageJ" button from the non-ImageJ frame. You'll see that the ImageJ main window and the image window dispose as desired (using this code from ImageJ Legacy).
However, there are (at least) three problems:
This example does not hook up the ij.getContext().dispose() call to the actual ImageJ1 UI window closing event. And doing that would not be trivial (I say without having dug deeply in this code recently).
After disposing ImageJ, as well as the extra JFrame, the JVM is supposed to shut down. We put a lot of effort into making it do so, actually. But it actually doesn't with the current version of ImageJ, presumably due to some undisposed resource(s) somewhere. This is a bug.
Clicking the X on the main ImageJ window shuts down the entire JVM, because ImageJ1's exitWhenQuitting flag gets set to true. You could toggle it back to false yourself, but this is actually tricky due to class loading issues relating to the fact that ImageJ2 patches ImageJ1 at runtime using Javassist.
The next question is: How badly do you really need this to work?
*I'm sorry for all of the trouble I may have caused you guys.
So, I am extremely new to programming with just a little experience in Java and Python. I was trying to make a program that would open a frame. In this frame there would be a button. When clicked, this button would play a song. I used a "recommended" code from YouTube. The code would begin to run, and then just stop. No frame would ever even appear. I showed it to a more experienced friend of mine. He said that the exact code ran just fine on his computer. I then sent him a screenshot of my project displayed on eclipse. He said that my JRE seemed to be missing some files. I tried a code that would just create a window, but it had the same problem. I am not sure what the JRE is, but I currently have JRE7. I don't know what I should do to fix this. Please help.
Error List
Severity and Description Path Resource Location Creation Time Id
The public type TopLevelWindow must be defined in its own file TGProject/src Frame.java line 4 1390698271752 73
The type TopLevelWindow is already defined TGProject/src TopLevelWindow.java Unknown 1390699351785 77
The method show(boolean) from the type Component is deprecated TGProject/src sound.java line 16 1390702839525 78
A link to the what my eclipse shows.
http://gyazo.com/3afdfa4f6750420f4e46deec40389340
A link to my Java file.
http://gyazo.com/257481d4ae9e2bb1d0ca93415a6c547e
Code for music
import java.awt.event.*;
import javax.swing.*;
import sun.audio.*;
import java.io.*;
public class sound {
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(200,200);
JButton button = new JButton("Click me");
frame.add(button);
button.addActionListener(new AL());
//this is outdated, but should still work
frame.show(true);
}
public static class AL implements ActionListener{
public final void actionPerformed(ActionEvent e) {
music();
}}
public static void music()
{
AudioPlayer MGP = AudioPlayer.player;
AudioStream BGM;
AudioData MD;
ContinuousAudioDataStream loop = null;
try{
BGM = new AudioStream(new FileInputStream("Jambi.mp3"));
MD = BGM.getData();
loop = new ContinuousAudioDataStream(MD);
}catch(IOException error) {}
MGP.start(loop);
}
}
Code for Frame
import java.awt.*;
import javax.swing.*;
// Create a simple GUI window
public class TopLevelWindow {
private static void createWindow() {
//Create and set up the window.
JFrame frame = new JFrame("Simple GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel textLabel = new JLabel("I'm a label in the window",SwingConstants.CENTER);
textLabel.setPreferredSize(new Dimension(300, 100));
frame.getContentPane().add(textLabel, BorderLayout.CENTER);
//Display the window.
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
createWindow();
}
}
Error 1
The public type TopLevelWindow must be defined in its own file
You either need to change.
public class TopLevelWindow {
To:
class TopLevelWindow {
Or do as reported and declare a new class for TopLevelWindow
Error 2
The type TopLevelWindow is already defined
I'm not sure what that means, but it might be solved by fixing the first problem.
Warning 3
The method show(boolean) from the type Component is deprecated
For any deprecation warning, go to the relevant method in the Java Docs. They should give details about what to use instead.
Tips
Compile often and ask as soon as you have a single error you do not understand.
Don't try to run code that shows problems in that window. Only experts should even try that.
You catch more flies with honey than with vinegar. Don't take the tone you did with Jayan, even if you think they are being harsh. People help for free, so have little time for questions that do not come up to standard. It might have been better to explain to the person that the question had now changed. Perhaps that would have made no difference to them, but either way, adding that kind of reply discourages everyone from helping.
"I used a "recommended" code from YouTube." Don't use YouTube videos to learn programming. They are often old, and in this case, they are using classes in the sun package for which there were better replacements since Java 1.3.
If you're really that new to programming, I would suggest to use an IDE (development environment) like for instance Netbeans or Eclipse and create a new JFrame form. You can then use the design view to graphically design your interface, IE drag your button on the screen. No need to go around programming frames. All you need to code is the implementation; what happens after you click the button.
After you posted the code, I had another look and this is what I've found:
Both classes have main methods. I ran both and each opened up a different window for me. Typically, you'll only want one main method. It's the main method! It's the starting point of your program and you can of course only have one starting point. At this time, your program is going to do two different things depending on what main method you run.
Still, this isn't your issue, because both mains are running for me. I think you must have the wrong version of java or something?
What I think you did is you pasted all that code into a file that wasn't called exacly "TopLevelWindow". If so, do that. I think your problem will go away.
Remember to only have one class per file, (barring inner classes; not something to concern yourself with as a beginner).
Okay, I understand your need for an SSCCE, so I created (my first) one.
I managed to replicate the problem with under 200 lines of code. On my system this demo compiled and ran perfectly (only the flickering was still there of course).
I stripped everything that had nothing to do with it. So basically we have two source files now: the screen manager and the game manager.
The screen manager:
http://pastebin.com/WeKpxEXW
The game manager:
http://pastebin.com/p3C5m8UN
You can compile this code with this make file (I use a ported version of Linux' make for Windows):
CC = javac
BASE = nl/jorikoolstra/jLevel
CLASS_FILES = classes/$(BASE)/Game/GameMain.class classes/$(BASE)/Graphics/ScreenManager.class
jLevel: $(CLASS_FILES)
#echo Done.
classes/%.class : src/%.java
#echo Compiling src/$*.java to $# [command: $(CC) src/$*.java ] ...
#$(CC) -Xlint:unchecked -d classes -classpath src src/$*.java
Where the source files are placed in the /src directory and the classes in the /classes directory.
After compilation to byte-code the game can be started using the following .bat file:
#set STARUP_CLASS=nl.jorikoolstra.jLevel.Game.GameMain
#set ARGUMENTS=1280 1024 32
#java -cp classes;resources %STARUP_CLASS% %ARGUMENTS%
Note that the ARGUMENT variable depends on your own screen settings and that you have to change it so that the game is displayed in the right resolution for your screen.
I see why it is flickering ----
BufferStrategy is doing a separate painting job from the Component's paint() method and they seem to use different Graphics objects and they are refreshing at a different rate --
when paint() is invoked before show(), it's fine. But
when paint() is invoked after show(), it will repaint the component to its initial blank look -- so flashing happens.
It's very easy to eliminate the flickering: override paint() method of your JFrame (GameMain) as you don't need it to do anything (BufferStrategy can give you more precise control on painting stuffs):
#Override
public void paint (Graphics g) {}
That's all. (I have tested it and it works fine, hope this may help :))
===== Update =====
Instead of overriding paint() method, a better way is to call setIgnoreRepaint(true) for your JFrame (GameMain) -- this method is just designed for such purposes! USE IT!
private GameMain(String ... args)
{
setIgnoreRepaint(true);
.....
}
This is how i implement double buffering, might help you get the concept.
Note it's implemented in a JPanel, but i think it can be implemented in other containers:
TheJApplet.java:
import java.awt.*;
import javax.swing.*;
public class TheJApplet extends JApplet
{
private Image myImage;
java.net.URL GameURL = CheckerGameJApplet.class.getResource("GameIMG");
String GamePath = GameURL.getPath();
#Override
public void init()
{
String GraphPath = GamePath+"/";
File myImage_File = new File(GraphPath+"myImage.jpg");
try
{
myImage = ImageIO.read(myImage_File);
}
catch (IOException ex)
{
// Add how you like to catch the IOExeption
}
final TheJPanel myJPanel = new TheJPanel(myImage);
add(myJPanel);
}
}
TheJPanel.java:
import java.awt.*;
import javax.swing.*;
public class TheJPanel extends JPanel
{
private int screenWidth = 500;
private int screenHeight = 500;
private BufferedImage BuffImg = new BufferedImage
(screenWidth,
screenHeight,
BufferedImage.TYPE_INT_RGB);
private Graphics2D Graph = BuffImg.createGraphics();
private Image myImage;
public TheJPanel(Image myImage)
{
this.myImage = myImage;
repaint();
}
#Override
public void paintComponent(Graphics G)
{
Graphics2D Graph2D = (Graphics2D)G;
super.paintComponent(Graph2D);
if(BuffImg == null)
{
System.err.println("BuffImg is null");
}
Graph.drawImage(myImage, 0, 0, this);
Graph2D.drawImage(BuffImg, 0, 0, this);
}
}
Hope this helps, good luck.
I have a cross-platform Java AWT-based program with animation. It had flashing problems until I strictly followed the example code at in the Java BufferStrategy documentation. However I'm using an AWT Canvas embedded in a Swing hierarchy, not full screen as you. You can see the code here if interested.
Another thing to note is that the AWT pipeline uses OpenGL primitives for good performance, and OpenGL support is buggy in many video drivers. Try installing latest versions of drivers for your platform.
It may work for you, when you set your hwnd.createBufferStrategy(2) in its own method.
There was a problem with Java rendering transparent background GIF images. That could be the problem.
I find it rather difficult to answer your question without an SCCSE. I also wonder what the RepaintManagerResetter does.
You might want to set your background color to some fancy colors like 0xFF00FF to find out if someone "clears" the background before the drawing happens. If the flicker image is purple, it's that - if it contains garbage or old images, it's probably the double-buffering.
In any case I would try to ensure that noone draws expect yourself. First, try to prevent native Windows code from drawing the window background. Set this once:
/*
* Set a Windows specific AWT property that prevents heavyweight components
* from erasing their background.
*/
System.setProperty("sun.awt.noerasebackground", "true");
Also, make sure that you override this in your JFrame(if you are using Swing components)
#Override
public void paintComponent(Graphics G)
{
// do not call super.pC() here
...
}
If that doesn't help, please provide a working example of your code, so people can reproduce the problem.
I'm trying to get a basic Swing Application to run on my Mac OS X 10.8.2 (Java version 1.6.0_37) machine, and every time I try to run it from Eclipse, the frame appears, but I can't interact with it.
I've tried to start from a basic, clean slate where I create a new Swing Application Window project in Eclipse (WindowBuilder->Swing Designer->Application Window). This generates the following skeleton code:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.BorderLayout;
public class Test {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Test window = new Test();
window.frame.setVisible(true);
window.frame.pack();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Test() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnPress = new JButton("Press");
frame.getContentPane().add(btnPress, BorderLayout.CENTER);
}
}
Everything seems to be fine, but when I run this from Eclipse, the frame doesn't let me interact with any components (in my non-example code, there are buttons and tabs).
Also, in the console, I see things like:
2012-11-09 14:30:27.624 java[8107:707] [Java CocoaComponent compatibility mode]: Enabled
2012-11-09 14:30:27.626 java[8107:707] [Java CocoaComponent compatibility mode]: Setting timeout for SWT to 0.100000
Is there some Mac-specific setting that I have to change? (I'm using the latest default Mac JRE)
The program runs fine on my machine under OSX, but it could be the missing
window.frame.pack();
Have you tried this?
Test window = new Test();
window.frame.pack();
window.frame.setVisible(true);
I had the same problem when using the DJ Swing library in my application (it uses SWT). Interestingly, the problem occurred even though I didn't initialise DJ Swing explicitly. It now works because I have added DJ Swing initialisation:
public class SwingAppTest {
public static void main(String[] args) {
NativeInterface.open();
UIUtils.setPreferredLookAndFeel();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Example");
frame.getContentPane().setLayout(new BorderLayout());
frame.setPreferredSize(new Dimension(400, 200));
frame.setBounds(0,0,200,200);
frame.setTitle("blah");
JButton blah = new JButton("blah");
blah.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("button clicked");
}
});
frame.getContentPane().add(blah, BorderLayout.CENTER);
frame.setVisible(true);
}
});
NativeInterface.runEventPump();
}
}
Apple is no longer supporting Java in is operating systems after 10.6:
Apple not committing to Java support in Mac OS X 10.7
seems like missing or incompatible library files in the JRE.
that is weird. I tried your sample (no linux) and don't see any problem there.
So as Wayne mentioned, might be macos issue.
Btw, what is your java version you're using?
On the other hand problem might be in the code you didn't share with us => hard to guess :)
EDIT: OK, so it seems you're playing "guess what I have in my code" game with us :) As my assumption is that code not shown causes problem.
It reminds me of some of these Poiroit/Agatha Christie detective stories, where just a little detail might have significant impact on the reality.
This is the reason for my theory:
code shown uses Java swing library (import javax.swing. ...) + Awt (import java.awt. ...) - this combonation is a common use case, however
the error message you shared shows SWT library error (Setting timeout for SWT to 0.100000)
So to me it seems like you're mixing things that should never be mixed.
As Swing is java UI library that is completely OS independent (originally Sun made) that is built on top of Awt. However SWT is completely different java UI library which is kind of mix of native calls with java on it (originally IBM made).
Therefor I'd suggest to double check your code and make sure that if you use JFrame, the only library components you have there are from Swing (javax.swing....) / Awt (java.awt. ...).
I've been knocking my head against a wall for days trying to get this working and finally found the answer:
'It's solved now - it was just a case of removing swt.jar from the project dependencies.'
Hey presto!!!!
In my case, I was trying to code a game where I used jPanel. I needed to override the paint method and added pack(); to the main and it finally showed me what I was trying to draw.
I am trying to create my first GUI application using (Java + Eclipse + Swing). This is my code:
import java.awt.*;
import javax.swing.*;
public class HelloWorldSwing extends JFrame {
JTextArea m_resultArea = new JTextArea(6, 30);
//====================================================== constructor
public HelloWorldSwing() {
//... Set initial text, scrolling, and border.
m_resultArea.setText("Enter more text to see scrollbars");
JScrollPane scrollingArea = new JScrollPane(m_resultArea);
scrollingArea.setBorder(BorderFactory.createEmptyBorder(10,5,10,5));
// Get the content pane, set layout, add to center
Container content = this.getContentPane();
content.setLayout(new BorderLayout());
content.add(scrollingArea, BorderLayout.CENTER);
this.pack();
}
//============================================================= main
public static void main(String[] args) {
JFrame win = new HelloWorldSwing();
win.setTitle("TextAreaDemo");
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.setVisible(true);
}
}
The code was taken from here.
When I run the application from Eclipse the expected window appears (So, it's good. I see what I want to see). However, when I try to close the window or try to write something in the text area the program freezes. The OS writes me that program is not responding (I try it on Ubuntu).
Can anybody help me to find the reason of the problem?
Thank you in advance for any help.
I'm sure this doesn't have to do with the code, as others have found the code runs just fine on their machines - which points to a machine specific issue. From within Eclipse, make sure it is setup to use the expected JDK/JRE. However, before worrying about how Eclipse is handling your situation, I'd run things by hand first - especially since you've got a very simple class.
I would check to ensure that you're using the expected compiler and runtime. On Linux:
which javac
which java
If they're both what you expect, do the following:
javac HelloWorldSwing.java
java HelloWorldSwing
If you get a similar problem, then you know it's not the Eclipse configuration and it's something else. If you're not using the latest JDK, upgrade to the latest. If you're already at the latest, it could be a display driver. Do other JAVA swing programs work on this computer? I'm sure you could find some on the net, download an app already packaged as a jar and try running it.
did you try using the eventdispatcherthread to view the JFrame?
something like:
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
createAndViewJFrame();
}
});
}
public void createAndViewJFrame(){
JFrame win = new HelloWorldSwing();
win.setTitle("TextAreaDemo");
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.setVisible(true);
}
then your frame would be shown by the swing dispatcher thread.
hope it helped, although im just guessing...
Update: as commenters pointed you i f**ed up the invokeLater() call. I just edited this post to correct that. Thanx go to yishai & willcodejavaforfood for pointing it out!
frank
You need to catch the exit event and
respond with a System.exit( 0 );
You should be able to find that in
most swing examples online.
wrong stuff... sorry... coffee... argh....