问题描述
在我的应用程序中有许多视图(子组件)和只有一个控制器。在一个视图中选择一些选项可以更改另一个视图中的组件布局和数量。
控制器初始化视图,然后创建所有子组件。
在这样的应用程序中,控制器需要引用所有子组件。子组件?
在一个视图中的侦听器中调用控制器来执行操作,然后需要更新另一个视图。
我觉得控制器不应该引用所有的视图,但不知道在哪里形成。
Head第一个设计模式书中的示例只有一个视图,所以我被卡住了。
++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++
我写的游戏是一个跳棋(草稿)游戏。在一种情况下,当计算机对抗自身时,用户必须在游戏开始之前选择一些选项。一个这样的选择是在游戏期间的某些时段选择游戏策略。比如当它在板上有12到8块时它会攻击更多,在板上8到4块它会更具防御性。
目前游戏GUI的结构方式是,有一个整体的JPanel(RightContainerFrame),其中包含其他JPanel;然后有一个JPanel(StartGamePanel),用户可以在其中配置游戏。还有一个包含选项卡的JTabbedPane(jTabbedPane1)。当用户在JComboBox中选择某个选项时,当前在StartGamePanel中,需要在jTabbedPane1中添加或删除选项卡。
我目前实现此目的的方式是在StartGamePanel
RightContainerFrame.getInstance()。generateAndDisplayPlayerTwoRangeTabs(numberOfRangeTabsNeeded);
现在我知道这是错的,因为我有一个视图,StartGamePanel通过调用另一个容器视图RightContainerFrame中的方法直接更改另一个视图JTabbedPane。
我是对如何构建此问题的任何建议持开放态度。
首先,我可以将 jComboBox1ActionPerformed
方法移动到控制器。这可以更新jTabbedPane1的模型。或者它可以直接在jTabbedPane1中调用方法来显示所需的选项卡数。
Swing不是真正的MVC架构:它是一个模型/(视图+控制器)。每个JComponent都是视图和控制器。
您需要定义与组件上的某个事件关联的回调方法(也称为事件侦听器)。对于不同的JComponents,不同类型的事件有不同类型的事件侦听器。
这是一个例子,其中一个事件监听器在一个按钮上注册,当它被点击时,它会改变另一个组件中的文本(myJLabel):
jButton1.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent event){
myJLabel1.setText(你刚刚点击了一个按钮。);
}
}
//你可以将其他ActionListeners添加到同一个jButton1
您可以拥有一个处理所有事件的全局控制器,但您需要将其注册为每个组件的侦听器。当全局控制器收到 event
,它可以查询它以找出它来自哪个按钮并相应地更改其他JComponent。所以,是的,你的全局控制器需要引用所有JComponents,除了作为监听器注册到所有人之外。全局控制器不仅需要实现ActionListener,还需要实现上面的鼠标点击,以及所有其他类型的EventListeners需要处理来自其他组件的所有其他类型的事件。
它可能不是一个好的有一个全局控制器的想法,因为它可能最终成为一个非常大的类。让每个JComponent注册一个(或多个)直接改变其他组件的事件监听器就足够了。
EDIT :
我不太确定拥有一个全局控制器是个坏主意:你最终得到了一个庞大的类,但至少所有的回调逻辑都在一个地方。
In my application there are many views(sub components) and only one controller. Selecting some options in one view can change the layout and number of components in another view.The controller initialises the view, which in turn creates all the sub components.
In an application such as this does the controller need to have a reference to all the sub components?As in a listener in one view calls the controller to carry out the action and then needs to update the other view.I feel that the controller should not have a reference to all the views but dont know where to go form here.The example in the Head first design patterns book only has one view so I am stuck.
++++++++++++++++++++++++
More detail.The game I am writing is a checkers (draughts) game. In one scenario when the computer is playing against itself the user has to choose some options before the game starts. One such option is to choose the games strategy for certain periods during the game. Such as when it has 12 to 8 pieces on the board it will attack more, 8 to 4 pieces on the board it will be more defensive.
The way the game GUI is structured at the moment, is that there is one overall JPanel (RightContainerFrame) this contains the other JPanels; there is then one JPanel (StartGamePanel) in which the user can configure the game. There is also a JTabbedPane (jTabbedPane1) which contains tabs. Currently in the StartGamePanel when a user selects a certain option in a JComboBox, tabs need to be added or removed from jTabbedPane1.
The way I achieve this currently is in StartGamePanel
RightContainerFrame.getInstance().generateAndDisplayPlayerTwoRangeTabs(numberOfRangeTabsNeeded);
Now I know this is all wrong as I have one view, StartGamePanel directly changing another view JTabbedPane by calling a method in another there container view RightContainerFrame.
I am open to any suggestions as to how to structure this problem.
First I could move the jComboBox1ActionPerformed
method to the controller. This could either update a model for the jTabbedPane1. Or it could call a method directly in the jTabbedPane1 to display the number of tabs required.
Swing is not a true MVC architecture: it's a model/(view+controller) architecture. Each JComponent is both a view and a controller.
You need to define callback methods (aka event listeners) which you associate to some event on the components. There are different types of event listeners for different types events on the different JComponents.
Here's a example where an event listener is registered on a button such that when it is clicked, it changes the text in another component (myJLabel):
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
myJLabel1.setText("You just clicked a button.");
}
}
// you can add other ActionListeners to the same jButton1
You could have a global controller that handles all events, but you would need to register it as an listener for each component. When the global controller received the event
, it can query it to find out from which button it came from and change other JComponent(s) accordingly. So, yes, your global controller would need references to all JComponents, on top of being registered to all of them as a listener. The global controller would need to implement not just ActionListener, as above to get the mouse clicks, but also all other types of EventListeners needed to handle all the other types of events from the other components.
It might not be a good idea to have a global controller because it could end up being a very large class. Just letting each JComponent registering one (or many) event listener(s) that directly change some other component(s) should be sufficient.
EDIT:
I am not so sure it's a bad idea to have a global controller: you end up with a huge class, but at least all the callback logic is in one place.
这篇关于MVC很多视图和一个控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!