The class javax.swing.JComponent is a direct subclass of javax.awt.Container, which provides methods to add child components. While this makes sense for some components, like JTable or JTree, it doesn't seem to make sense for JLabel, for example. As far as I could tell from simple experiments, children of a JLabel are ignored.
Is there a good reason that all JComponent subclasses are also subclasses of Container, or is it just a relic of the days of overzealous subclassing?
Why is JComponent a subclass of Container?
You can add child components to any component. You may get different behaviour than you would if you add components to a panel, but it can be done. For most components, other than a JPanel, a null layout is used.
While this makes sense for some components, like JTable or JTree,
Why do you say this. A JTable is just a component. The normal display of a JTable does not have any child components. When you edit a cell, the editor component is added to the table and the table will manage the size/location of the component.
it doesn't seem to make sense for JLabel, for example. As far as I could tell from simple experiments, children of a JLabel are ignored.
Since the layout is null you need to manage the size/location of any component you add to the label.
Or, you can set the layout manager of the JLabel. Note the actual size of the label will not include the children, but you can position the children on the label using the layout manager.
Related
I am writing a class that extends mx.core.UIComponent. In the constructor of this class, I would like to add a Button (spark.components.Button). However, creating a new Button object (such as var b:Button = new Button();) and then doing this.addChild(b) doesn't work -- no button is appearing. Is there any reason why a Button object can't be added as a child?
Edit: Just to add, when I print out the children, it says that the Button object is a child, but the Button doesn't show up.
You need to add the button in the createChildren method not in the constructor.
protected var button:Button;
override protected function createChildren():void {
super.createChildren();
button = new Button();
addChild(button);
}
Depending on what you are trying to do you may also need to implement the measure and updateDisplayList methods.
Using UIComponent directly, you aren't getting the layout of the child handled for you; you would need to set the position and size of your child components manually (see docs).
Consider using a Group (or Canvas, if you're still on MX components) to handle child layout. You can still add rendering in updateDisplayList, just make sure you call super.updateDisplayList() as well.
You need to read up on the differences between ActionScript components and Flex components. When using a Flex component, you must use container.addElement( element ), not container.addChild( child ). As far as I am aware, the only classes with this functionality descend from Group (at least in the Spark framework, the one I am most familiar with). So extending UIComponent will not allow you to add a Button, although a UIComponent can be added to a Flex container (which I do not believe a normal Sprite can do)
Hopefully a quick question here. I have setup a "LayoutPage" custom class (based on MovieClip) and I am attemptimg to create a "selected" behaviour.
When I assign my "addEventListener(MouseEvent.CLICK,toggleSelection)" from within my custom class, everything works as expected, clicking any object of that class does display the correct behaviour.
Now, I would like to extend the functionality by adding keyboard modifyer to either extend the selection or replace it.
For this, I thought of moving the "addEventListener" out of the class and put it inside the parent instead (my "PageLayout" class where all the "LayoutPage" live). But by doing so, the click event no longer register on the "LayoutPage" class but rather on its individual children (Page icon, Page number text field, Page Highlight shape, etc.)
Can anybody explain why this is happening and how I can circumvent it?
TIA
This should be happening no matter where you put your addEventListener. It is because mouseChildren is switched on by default. It is probably best to turn it off inside your LayoutPage class like so:
myLayoutPage.mouseChildren = false;
The actual issue is that use are probably using currentTarget to reference the item that was clicked on in your event handler method. Take a look at the descriptions for currentTarget and target to get a good idea of how they differ.
A good option would be to add your listener at the PageLayout level, but add it specifically to each LayoutPage child like so:
myLayoutPage.addEventListener(MouseEvent.CLICK, toggleSelection);
This way you can just use target in your handlers. But it would probably be best to still switch mouseChildren to false on each of your LayoutPage instances.
I'd like to conditionally hide a tab in a TabNavigator. It seems that setting visible doesn't work properly (presumably because this is how the TabNavigator hides the tabs that aren't currently selected).
What's the right way to do this?
You can do this by making use of TabNavigator's getTabAt() method which returns the Button that makes up the visual tab. You can then set that Button's visible property. It's a little tricky to get this setup with a bindings, but it's doable.
You could also consider just disabling the tab instead, which you can do by setting enabled on the corresponding TabNavigator child (for which visible didn't work).
What do you mean by hide? If you actually mean remove, then just take your array that's bound to the data in the TabNavigator, and remove the applicable element from it.
If you want to just have them removed temporarily, create a component of your own that encapsulates the TabNavigator and has an array of removed tabs and an array of actual tabs. Then handle this as you see fit.
You might want to check out the flexlib project. They have a component called SuperTabNavigator that adds a lot of functionality to the base Flex TabNavigator, including hiding tabs (I think).
If you do have to create your own component, though, it's a bit more tricky. The thing to know is that "tabs" are actually specially styled buttons, contained within a TabBar component (the TabBar is then contained within the TabNavigator). What you'll have to do then, is subclass TabNavigator and have some property on your views (i.e. the canvases, etc. that are added to the TabNavigator) that is bound to the visible and includeInLayout properties of the TabBar buttons.
In essence, what you'll have is something like:
BindingUtils.bindProperty( tabButton, "visible", view, "someProperty" );
BindingUtils.bindProperty( tabButton, "includeInLayout", view, "someProperty" );
I don't know about TabNavigator, but in other containers, you can set the includeInLayout property to false and it will be ignored. You probably still need to combine it with visible.
var secondTab = tabNavigator.removeChildAt(0);
How do I overlay widgets in Qt?
I want to create some widgets and place them out-of-layout, but rather tweak their size and position when some other widget's geometry is changed.
Something like the buttons on the screenshot:
You just need to create your QPushButton (or any QWidget), indicate its parent QWidget and then display it.
Don't add it to the parent layout else you will not be able to move it as you want.
Don't forget to indicate its parent else it will be displayed as independant QWidget.
In these conditions your QPushButton will be considered as child of the QWidget but not member of the parent's layout. So it will be a "floating" child and you must manage it's behaviour when resizing parent's QWidget.
If you want a unified behaviour for all overlay buttons, you should subclass QLayout and redefine members bahaviour.
If they're child of a widget without a layout, you should be able to move them around as you please, I think.
I needed a widget like this for a project I'm working on, so I took Patrice advice and wrote this code (Python) PyQt4 Widget Overlay
I inherited a custom component from TextField. The component needs to know when any of its styles got changed at runtime via setStyle. How would I do that? It's probably obvious but I couldn't find an event or appropriate method to override.
If you want the text field to play nicely with containers and other components in Flex you may want to wrap it in a UIComponent, or have the subclass implement the IUIComponent and IStyleClient or ISimpleStyleClient interfaces (which UIComponent implements). If you do the component will work with Flex' style system and every time a style changes a method calledstyleChanged` will be called:
public function styleChanged(styleProp:String):void
See http://livedocs.adobe.com/flex/3/langref/mx/core/UIComponent.html#styleChanged()
styleChanged () method
public function styleChanged(styleProp:String):void
Detects changes to style properties. When any style property is set, Flex calls the styleChanged() method, passing to it the name of the style being set.
This is an advanced method that you might override when creating a subclass of UIComponent. When you create a custom component, you can override the styleChanged() method to check the style name passed to it, and handle the change accordingly. This lets you override the default behavior of an existing style, or add your own custom style properties.
If you handle the style property, your override of the styleChanged() method should call the invalidateDisplayList() method to cause Flex to execute the component's updateDisplayList() method at the next screen update.
Parameters styleProp:String — The name of the style property, or null if all styles for this component have changed.