index.lxp@lxpwrap=c4631_252ehtm.htm
来自「GUI Programming with Python」· HTM 代码 · 共 794 行 · 第 1/2 页
HTM
794 行
<table border="0" cellspacing="0" cellpadding="3" width="100%"><tr><td> <div align="center" id="bldcontent"> <a href="../default.htm"><img src="../images/opendocs.png" width="63" height="76" border="0"></a> <br> <div class="symbol">Your OpenSource Publisher™</div> </div> </td></tr></table> <div align="center" class="author"> <a href="../products.lxp">Products</a> | <a href="../wheretobuy.lxp">Where to buy</a> | <a href="../bookstore.lxp">Retailers</a> | <a href="../faq.lxp">FAQ</a> | <a href="../writeforus.lxp">Write for Us.</a> | <a href="#contact">Contact Us.</a> </div> <table border="0" cellspacing="3" cellpadding="0" width="100%"><tr><td width="100%"> <div class="content"> <table border="0" cellspacing="2" cellpadding="0" width="100%"><tr><td width="100%"> <div align="center"><H4 CLASS="AUTHOR"><A NAME="AEN5">Boudewijn Rempt</A><br><a href="../../https@secure.linuxports.com/opendocs/default.htm"><img src=odpyqt125.png></a><br>ISBN: 0-97003300-4-4<br><a href="../../https@secure.linuxports.com/opendocs/default.htm">Available from bookstores everywhere or you can order it here.</a><p>You can download the source files for the book <a href="pyqtsrc.tgz">(code / eps) here.</a><hr></div> <HTML><HEAD><TITLE>Application Frameworks</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.72"><LINKREL="HOME"TITLE="GUI Programming with Python: QT Edition"HREF="book1.htm"><LINKREL="UP"TITLE="Creating real applications with PyQt"HREF="p4627.htm"><LINKREL="PREVIOUS"TITLE="Creating real applications with PyQt"HREF="p4627.htm"><LINKREL="NEXT"TITLE="Macro languages"HREF="x4760.htm"></HEAD><BODYCLASS="CHAPTER"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">GUI Programming with Python: QT Edition</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><A accesskey="P" href="index.lxp@lxpwrap=p4627_252ehtm.htm">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><A accesskey="N" href="index.lxp@lxpwrap=x4760_252ehtm.htm">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="CHAPTER"><H1>Chapter 12. Application Frameworks</A></H1><DIVCLASS="TOC"><DL><DT><B>Table of Contents</B></DT><DT><A href="index.lxp@lxpwrap=c4631_252ehtm.htm#AEN4637">Architecture: models, documents and views</A></DT><DT><A href="index.lxp@lxpwrap=x4760_252ehtm.htm">Macro languages</A></DT><DT><A href="index.lxp@lxpwrap=x4782_252ehtm.htm">Project layout</A></DT></DL></DIV><P>Up to this point we have seen only example scripts— Exciting examples, illuminating examples, promising examples, but still just examples. Example scripts are far removed from the realities of a complex GUI application. For a complex application you need a well thought-out modular structure, where each component can find its place. You need an architecture, and you need a design.</P><P>Most books on programming languages don't progress much beyond basic examples; indeed, it is not really possible to discuss a complete, complex application. Still, in this part of the book I want to show how BlackAdder and PyQt can help you achieve a well-written, maintainable application, starting with the architecture, and then moving on to the outlines of an application. On the way, I'll show you one useful way of laying out the project structure. In the next few chapters we'll build this framework into a real application.</P><DIVCLASS="SECT1"><H1CLASS="SECT1">Architecture: models, documents and views</A></H1><P>Let's start with the basics. Applications are, essentially, interfaces that manipulate data. Whether you are handling records from a database, an object tree from a parsed HTML page, a game world, or a stream from a network socket, there is always a reality that is mediated to the user with an interface.</P><P>From this, it follows naturally that it would be a good idea to separate bits of software that handle the data from the interface. After all, you might want to manipulate the same data with a different interface. In some development environments this is quite difficult to achieve. Visual Basic, for instance, almost mandates that you entangle your data-mangling code with your GUI code. On the other side of the scale, SmallTalk has explicit support for the most extended form of the celebrated <SPAN><ICLASS="EMPHASIS">Observer</I></SPAN> pattern — with the Model/View/Controller framework for the SmallTalk user interface (or, in later versions, the Model-View-Presenter architecture).</P><P>The component that represents the data is variously termed <SPAN><ICLASS="EMPHASIS">model</I></SPAN> or <SPAN><ICLASS="EMPHASIS">document</I></SPAN>; the component that actually shows the data on screen is the <SPAN><ICLASS="EMPHASIS">view</I></SPAN>. The model-view-controller framework adds a <SPAN><ICLASS="EMPHASIS">controller</I></SPAN> component, which represents the user input.</P><P>The controller component receives mouse clicks, key press events and all other user input, and passes those on to the model. The model determines its current state from that input, and notifies the view that its representation of the model should be changed. Sounds like PyQt signals and slots would come in handy, doesn't it?</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>Model-view-controller architecture</P></DIV></P></DIV><P>Be aware of the ‘fractal' nature of this architecture. You can envision your entire application divided into two or three parts — one component for the model, one for the view, and perhaps one for the controller. However, the same tripartition can be designed for the lowliest checkbox class. Here, the boolean value is the model, the picture of a box with a cross in it is the view, and the event handler is the controller.</P><P>Swing, the Java gui toolkit, does exactly this, and gives you the opportunity to write specialized models and controllers for almost all its widgets (and specialized views, too). PyQt doesn't go quite that far, and its widgets are based on a simpler, more monolithic model. Like all good ideas carried through to their extremes, writing models and controllers for every widget is a bit tiresome. That's why Java's Swing also presents capable default implementations for the controller and model parts.</P><P>This chapter is about application architecture, and when speaking of views and models, documents and controllers, I do so only at the application architecture level, not the widget level. However, a complex application could consist of several models and views: for instance, in an application based on a database, you could view every table as a model and every corresponding form as a view.</P><DIVCLASS="SECT2"><H2CLASS="SECT2">A document-view framework</A></H2><P>The most basic architecture in which application model and interface are separated is the <SPAN><ICLASS="EMPHASIS">document-view</I></SPAN> paradigm. Here, you have two basic modules: one representing your data (the document), and one representing the interface that shows the data to the user (the view). This architecture is prevalent in the Windows world: the entire Microsoft MFC library is based on its principles, and it is also popular in the Unix world, where many KDE applications are based on it.</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>The document-view architecture</P></DIV></P></DIV><P>There must be an interface between the document and the view. Changes made in the view must be passed on to the document, and vice-versa. A simple document-view framework is readily constructed:</P><P>The basic application structure consists of three classes: an application class, a view class and a document class. In the next few chapters of this part, we'll work with the framework to build a real application. We'll also extend it to handle multiple document windows: the framework detailed below can only work with one document. The complete framework is in the file <TTCLASS="FILENAME">docview.py</TT>.</P><DIVCLASS="EXAMPLE"></A><P><B>Example 12-1. A simple document-view framework</B></P><PRECLASS="PROGRAMLISTING">class DocviewDoc(QObject): def __init__(self, *args): apply(QObject.__init__, (self,)+args) self.modified=FALSE def slotModify(self): self.modified = not self.modified self.emit(PYSIGNAL("sigDocModified"), (self.modified,)) def isModified(self): return self.modified </PRE></DIV><P>You should always begin with designing the application model - or so the theory goes. Your preferences might lie with first creating a mock-up of the interface using generic widgets, in order to be able to have something concrete to talk about. That's fine with me. Anyway, the <TTCLASS="CLASSNAME">DocviewDoc</TT> class represents the <SPAN><ICLASS="EMPHASIS">document</I></SPAN> or the application model. This can be as complex as you want. This class merely remembers whether it has been modified. The controlling application can query the document using the <TTCLASS="FUNCTION">isModified()</TT> function to determine whether the document has changed, and it can hook a <TTCLASS="CLASSNAME">QAction</TT> to the <TTCLASS="FUNCTION">slotModify()</TT> slot to signal user interaction to the model. Separating all code that handles the application data makes it easy to write automated tests using Pyunit. This is the topic of the next chapter.</P><P><TTCLASS="CLASSNAME">DocviewView</TT> is the view class in the framework. A view is a visual component; in PyQt it must somehow descend from <TTCLASS="CLASSNAME">QWidget</TT> — either directly, as it is done here, or via a more specialized class, such as <TTCLASS="CLASSNAME">QTable</TT> or <TTCLASS="CLASSNAME">QCanvas</TT>. A reference to the application model is passed to the view. This breaks encapsulation somewhat, but it makes initially setting up the display a lot easier.</P><DIVCLASS="WARNING"><P></P><TABLECLASS="WARNING"BORDER="1"WIDTH="100%"><TR><TDALIGN="CENTER"><B>Warning</B></TD
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?