• Post Reply Bookmark Topic Watch Topic
  • New Topic

Assistance With JTabbedPane  RSS feed

 
Mark Andrew Davis
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey Team,

I hope you are all having a wonderful week!

I have decided to make a Notepad application like windows notepad as a learning curve. As such, I have hit a little road block.

ISSUE
I have a JMenuItem called NewDataItem which is supposed to create a new blank document in a JTab. But the issue is, when I press New it doesn't do anything.
Something I tested was making my (in TabbedPane class) a public static and it worked! YAY!! But, I don't know why...

I don't want to leave this as static unless I know I have too, but without first understanding the cause, it is best not too.

I have created my Tabbed Pane, Main Text Area and Toolbar all in different classes for now as I would like to expand on them over time.

Is anyone able to assist?

Code Bellow:


MAIN CLASS:


MainFrame Class


Main Text Area Class



ToolBar Class



Tabbed Pane Class

 
Paul Clapham
Sheriff
Posts: 22835
43
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There's a lot of code there which superficially looks pretty good. But as I was trying to find out what your New button was supposed to do, I became more and more dubious about your TabbedPane class.

So first, it extends JPanel so it's a JPanel. And when you create it you initialize it so it contains a JTabbedPane and nothing else (from the GUI point of view, anyway). But then it contains the setTabbedPane and getTabbedPane which you always call like this: setTabbedPane(getTabbedPane()). It looks to me like the purpose of this construct is to add a new tab to the JTabbedPane. So why not just have one method:



Next I looked at your ToolBar class. It extends TabbedPane, which extends JPanel.  Having ToolBar extend JPanel is sort of defensible, but having it extend TabbedPane is confusing, because it doesn't need to be a TabbedPane. And both the ToolBar class and the TabbedPane class have a private MainTextArea member, which is a recipe for confusion. It's probable that the error you're asking about stems from this.

However there's this rule of thumb: "Prefer composition over inheritance". In your case that means that a ToolBar object should have a reference to a TabbedPane object, rather than being one. Likewise a MainTextArea object should have a reference to a JScrollPane (in fact, it already does) rather than being a JScrollPane. I'd really recommend that you modify your code to follow that rule, because a lot of code looks like you inherited a class just to avoid creating an object of that class.
 
Paul Clapham
Sheriff
Posts: 22835
43
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also, for example: lines 5 and 6 of your MainTextArea class don't need to be there. Those variables could be local variables in the methods which use them. Also the textAreaMethod() method should be private, since the purpose of the class (apparently) is to be a factory which produces JScrollPanes which contain suitably-configured JTextAreas. Allowing it to return a JTextArea which isn't in a JScrollPane is beyond its requirements, no?
 
Mark Andrew Davis
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:
So first, it extends JPanel so it's a JPanel. And when you create it you initialize it so it contains a JTabbedPane and nothing else (from the GUI point of view, anyway). But then it contains the setTabbedPane and getTabbedPane which you always call like this: setTabbedPane(getTabbedPane()). It looks to me like the purpose of this construct is to add a new tab to the JTabbedPane. So why not just have one method:


Next I looked at your ToolBar class. It extends TabbedPane, which extends JPanel.  Having ToolBar extend JPanel is sort of defensible, but having it extend TabbedPane is confusing, because it doesn't need to be a TabbedPane. And both the ToolBar class and the TabbedPane class have a private MainTextArea member, which is a recipe for confusion. It's probable that the error you're asking about stems from this.

However there's this rule of thumb: "Prefer composition over inheritance". In your case that means that a ToolBar object should have a reference to a TabbedPane object, rather than being one. Likewise a MainTextArea object should have a reference to a JScrollPane (in fact, it already does) rather than being a JScrollPane. I'd really recommend that you modify your code to follow that rule, because a lot of code looks like you inherited a class just to avoid creating an object of that class.


Thanks Paul for your assistance.

- I have removed the extends TabbedPane from ToolBar
- I have also removed the private MainTextArea object from ToolBar and TabbedPane
- I have amended my code to include the above code you advised. This was actually my first way of doing things, but my issue I came across was that I didn't know how to properly pass reference to this through.
- At present i get a NullPointException when I press the New Document button, I am assuming this is due to the object not being initialized. That's due to the fact I don't know how I should pass this through correctly.

Are you able to review my changes and see if they fit more now? also could you please advise me on how I can pass reference Toolbar to TabbedPane correctly? I believe this is the reason why I turned to setters and getters in the first place(probably not the best approach).


TOOLBAR:


TABBED PANE:


MAINTEXTAREA


Thanks,
Mark.D
 
Paul Clapham
Sheriff
Posts: 22835
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mark Andrew Davis wrote:also could you please advise me on how I can pass reference Toolbar to TabbedPane correctly?


I'm sorry, I don't understand that. I don't see why a TabbedPane needs a reference to any Toolbar objects.

As for your MainTextArea class, the textArea variable should be private. You have a method which wraps it in a scroll pane and returns it, so there's no need to expose it to the world on its own. I also don't think you need to create and disregard a scroll pane in the constructor.
 
Mark Andrew Davis
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:
Mark Andrew Davis wrote:also could you please advise me on how I can pass reference Toolbar to TabbedPane correctly?


I'm sorry, I don't understand that. I don't see why a TabbedPane needs a reference to any Toolbar objects.

As for your MainTextArea class, the textArea variable should be private. You have a method which wraps it in a scroll pane and returns it, so there's no need to expose it to the world on its own. I also don't think you need to create and disregard a scroll pane in the constructor.


haha that's okay! I think maybe I am the one confused and creating a domino effect of confusion...

So what I want to do is, in ToolBar class I want to execute the bellow code so it will create a new blank tab. But when I run this I get a nullPointException.



tabbedPane.addTabbedPane(); refers to the bellow code added to TabbedPane calss:



Is this the wrong way to go about it?

As for the MainTextArea I used to have it as private but I couldn't get the OpenDataItem and SaveDataItem to work (Located in ToolBarClass)

In the OpenDataItem for example, I have the bellow code which works (because TextArea is public):



If I make it private I thought I should be able to do it as followed, but didn't work either:




Lately these are the kind of things I am having trouble with... Either making reference to another class, an object an method etc. This is the whole basis of object orientated programming, but I'm slowly starting to piece everything together.

I hope this makes some what sense? And thanks for your assistance again :)

Mark.D
 
Paul Clapham
Sheriff
Posts: 22835
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


Don't tell that object to request focus. Ask it to request focus.

What I mean by that is, if something owned by a MainTextArea object is supposed to request focus then there should be code in the MainTextArea class which requests focus for it. If you want something outside MainTextArea to ask for that to happen, then there should be a public method in MainTextArea which allows it to ask.
 
Paul Clapham
Sheriff
Posts: 22835
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mark Andrew Davis wrote:So what I want to do is, in ToolBar class I want to execute the bellow code so it will create a new blank tab. But when I run this I get a nullPointException.


You normally get a stack trace when an exception is thrown. It contains all sorts of useful information like the class, method, and line number where the exception occurred. In the case of a NullPointerException the thing to do is to look at the line identified at the top of the stack trace and see what variable unexpectedly had a null value.
 
Mark Andrew Davis
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:

Don't tell that object to request focus. Ask it to request focus.

What I mean by that is, if something owned by a MainTextArea object is supposed to request focus then there should be code in the MainTextArea class which requests focus for it. If you want something outside MainTextArea to ask for that to happen, then there should be a public method in MainTextArea which allows it to ask.


Are you able to assist me on how I can achieve this? I've tested a few different ways but I don't think I figure out the code on how to achieve this.

If it's okay could you please explain along with the code so I can learn? I much prefer trying to figure out for myself but I think I am going in circles haha.

Thanks paul :)
 
Mark Andrew Davis
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:
Mark Andrew Davis wrote:So what I want to do is, in ToolBar class I want to execute the bellow code so it will create a new blank tab. But when I run this I get a nullPointException.


You normally get a stack trace when an exception is thrown. It contains all sorts of useful information like the class, method, and line number where the exception occurred. In the case of a NullPointerException the thing to do is to look at the line identified at the top of the stack trace and see what variable unexpectedly had a null value.


Here is the stacktrace:



I am not 100% confident at reading this, but from what I can see is it is stating TollBar class Line 80 has a nullPointException

 
Paul Clapham
Sheriff
Posts: 22835
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mark Andrew Davis wrote:
Paul Clapham wrote:

Don't tell that object to request focus. Ask it to request focus.

What I mean by that is, if something owned by a MainTextArea object is supposed to request focus then there should be code in the MainTextArea class which requests focus for it. If you want something outside MainTextArea to ask for that to happen, then there should be a public method in MainTextArea which allows it to ask.


Are you able to assist me on how I can achieve this? I've tested a few different ways but I don't think I figure out the code on how to achieve this.

If it's okay could you please explain along with the code so I can learn? I much prefer trying to figure out for myself but I think I am going in circles haha.


Actually now that I thought about that today I realized that it's wrong. It would have been right if the MainTextArea class was managing a JTextArea. But it isn't, it's (nearly) a factory whose job is to produce a new JTextArea every time you call the (badly-named) textAreaMethod() method. So here's what I think now: that class should be a factory whose job is to produce nicely-configured JTextAreas. Nothing more than that. Your version hides the JTextArea in a JScrollPane, but that seems to be a problem because then you can't call setFocus on the JTextArea. So have it just produce JTextAreas and nothing else. If the caller wants to wrap them in JScrollPanes, let it do that. If it wants to call setFocus on them, let it do that too.
 
Paul Clapham
Sheriff
Posts: 22835
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mark Andrew Davis wrote:I am not 100% confident at reading this, but from what I can see is it is stating TollBar class Line 80 has a nullPointException



Yes, that's exactly right. And that means that the tabbedPane variable is null.

But if you accept my recommendation about the MainTextArea class, you wouldn't do that. You would write some code which gets a new JTextArea (from a MainTextArea object) and puts it into a scroller and adds that to the tabbed pane and sets the focus to point to it. You could of course put all of that into a method, which would be a good thing, but it would be a method of the class enclosing line 80 and not a method of some other class.

At least I think so. It's always hard to deal with the problem where somebody wrote a ton of code and then realized their object design was all out of whack and needed to be rethought. Which is very common with beginners starting with Swing GUIs.
 
Mark Andrew Davis
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:
Mark Andrew Davis wrote:I am not 100% confident at reading this, but from what I can see is it is stating TollBar class Line 80 has a nullPointException



Yes, that's exactly right. And that means that the tabbedPane variable is null.

But if you accept my recommendation about the MainTextArea class, you wouldn't do that. You would write some code which gets a new JTextArea (from a MainTextArea object) and puts it into a scroller and adds that to the tabbed pane and sets the focus to point to it. You could of course put all of that into a method, which would be a good thing, but it would be a method of the class enclosing line 80 and not a method of some other class.

At least I think so. It's always hard to deal with the problem where somebody wrote a ton of code and then realized their object design was all out of whack and needed to be rethought. Which is very common with beginners starting with Swing GUIs.


Thanks for all your assistance paul! You put it into easy to understand terms for me :) I will work on refactoring a few things and write some code to perform advised and let you know how I go.
 
Paul Clapham
Sheriff
Posts: 22835
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Good, let us know how you get on!

Just a comment about something in your code which led me down the wrong garden path: you have a class called MainTextArea, with a method called textAreaMethod(). The class is actually a factory for producing decorated JTextArea objects, and every time that method is called it returns a new JTextArea object. So, usually a designer would have called the class something like JTextAreaFactory, to indicate its purpose, and the method something like newJTextArea(), to indicate what it actually did. With names like that you (and I) would be more likely to realize that every time textAreaMethod() was called it returned a new JTextArea object, and therefore that calling it repeatedly to get a reference to the object was the wrong thing to do.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!