2009-10-06 6 views
1

Je commence à apprendre Delphi. J'ai donc décidé d'écrire une application comme MS Excel à partir de zéro. Dans un nouveau Form1, j'ai mis un composant TPageControl contenant seulement 1 page. Dans cette page, j'ai mis un TAdvStringGrid et un TPanel avec quelques boutons (button1, button2) et un menu Popup1 pour définir certaines actions sur la grille, comme copier une cellule, copier une ligne, supprimer une ligne, etc. Pour ce StringGrid, aussi, J'ai défini certaines propriétés, comme les couleurs, les polices, etc. J'ai ajouté une barre d'outils avec un bouton au formulaire principal, afin d'ajouter plus de pages au PageControl. La méthode OnClick de ce bouton définit deux actions:
1) pour ajouter une nouvelle Page2 au PageControl, et 2) pour ajouter un nouveau StringGrid dans la nouvelle Page2 créée. Ce nouveau StringGrid créé (défini à l'exécution) dans une nouvelle page d'un Tpagecontrol doit hériter (obtenir, copier, cloner, dupliquer) les propriétés et les méthodes du parent StringGrid déjà défini dans la première page au moment du design, et devrait être capable d'appeler le menu PopUp1 tout comme le parent StringGrid. Comment nous faisons cela? Au début, je pensais que je devais juste copier les propriétés StringGrid en utilisant assing(), mais en utilisant cette approche, le menu contextuel ne s'affiche pas lorsque je clique avec le bouton droit sur le nouveau StringGrid ... et les boutons (button1 et button2) de Form1 ne fonctionnent qu'avec le premier StringGrid mais pas avec le nouveau ajouté. J'ai lu quelque part qu'afin de résoudre ce problème, je pourrais dupliquer le composant StringGrid en utilisant l'écriture et lire TMemoryStream (enregistrer le parent chaingrid dans un memorystream, créer un nouveau chaingrid puis lire ce memorystream dans le nouveau stringgrid créé), donc j'ai fait, mais quand le programme exécute cette méthode de clonage de composant, j'obtiens une erreur d'exécution. :-(Clonage d'un composant TStringGrid

Je ne Chech soigneusement l'Aide Rien trouvé sur ce sujet semble qu'il n'y ait pas de bibliothèque de composants Delphi ou des composants tiers qui faire face à ce genre de tâche Quelqu'un peut-il aider, s'il vous plaît...? O)

+1

Tout en essayant d'apprendre Delphi est admirable, écrire une application « comme MS Excel » comme un projet d'apprentissage pourrait être considéré comme un peu ambitieux. Qu'est-ce qui est arrivé à la bonne ole '' Hello, World ''? –

+1

Non, il a la bonne idée. Vous n'apprendrez rien en essayant de créer un programme qui ne fait rien. Construire une feuille de calcul, même simple, enseignera toutes sortes de principes de programmation importants. –

+0

Thnak vous Mason, vous avez absolument raison. Je crois que l'écriture de programmes est la façon dont on peut vraiment apprendre la programmation. J'ai de l'expérience en Java, mais Delphi est complètement nouveau pour moi. Il y a beaucoup de choses à comprendre. Je crois qu'un projet «ambitieux» peut m'aider à apprendre les choses rangées et minuscules de cette langue/IDE, seulement si je continue à monter sur ce cheval sauvage. Merci! –

Répondre

0

Bonjour à tous, je suis en train d'apprendre Delphi

le style Delphi est de trouver/créer/acheter un composant qui fait le travail et les utiliser dans la conception du temps. Vous pouvez essayer de créer un composant personnalisé basé sur une grille ou utiliser TFrame. Voir les liens de Custom Component Development et les fichiers d'aide fournis avec Delphi.

Si vous avez vraiment besoin de cloner le contrôle dynamiquement, here est un exemple que j'ai trouvé qui utilise stream.ReadComponent.

+0

eed3si9n Cher, Je suis désolé pour mon ignorance, mais qu'est-ce que cela signifie « le sous-classement d'une grille »? J'ai vérifié l'aide dans Delphi, je ne peux pas voir le lien. La méthode pour TMemoryStream dans votre lien est exactement ce que j'ai essayé avant de demander ici dans StackOverflow ...J'utilise TAdvStringGrid (comme suggéré par Vegar) mais le TMemoryStream ne fonctionne pas avec. –

+0

@Biolyzer, selon Wikipedia "une sous-classe est une classe qui hérite de certaines propriétés de sa superclasse. [...] Les sous-classes et superclasses sont souvent appelées classes dérivées et de base, respectivement, termes inventés par le créateur C++ Bjarne Stroustrup." –

2

Je voudrais utiliser un tabcontrol au lieu d'un contrôle de page. De cette façon, vous obtiendrez plusieurs onglets, mais seulement une page et une grille. Je ferais alors une sorte de structure de données pour garder toutes mes informations de cellule, et rendrais cette structure à la grille. De cette façon, je peux avoir plusieurs structures, et laisser l'onglet actif décider quelle structure rendre. Vous obtiendrez également un couplage plus lâche entre votre interface graphique et votre logique, ce qui vous permettra de changer plus facilement les choses plus tard. Par exemple. Si vous devez importer certaines valeurs dans une feuille de calcul différente d'une cellule de la feuille de calcul en cours, vous pouvez charger une structure et sélectionner les valeurs souhaitées. Pas besoin de faire un gui pour la deuxième feuille de calcul du tout.

Pour un composant 3.party, je recommanderai TMS FlexCell et TAdvSpreadGrid. Cela vous donnera la plupart de ce dont vous avez besoin.

+0

Je vois. Cela semble vraiment une solution intéressante. Je dois vérifier si le rendu DataStructure fait le travail pour une petite grille et pour une grosse grille (beaucoup de colonnes et de lignes avec des données). À RunTime, si nous modifions quelque chose dans n'importe quelle grille, cette modification doit être mise en miroir dans la structure de données. Cela signifie écrire une routine pour boucler dans la DataStructure chaque fois que je fais un changement mineur dans la grille? Par exemple, je tape quelque chose dans la cellule [25,42], donc la méthode onclick de la grille appelle DataStructure, va chercher la grille de droite, trouve la bonne cellule et écrit la valeur, est-ce? –

+0

Yup, quelque chose comme ça. Il est important d'avoir une structure plutôt efficace en dessous, mais tant que les feuilles ne sont pas trop grandes, il ne devrait pas y avoir trop de problèmes. Une liste de paires [row-reference, list], où chaque liste contient une paire [column-reference, value] devrait faire l'affaire. Si vous gardez les listes triées, vous aurez une recherche assez rapide. Une solution plus simple consisterait à convertir la référence de cellule [ligne, colonne] en une sorte de valeur de hachage et à stocker des paires [hashvalue, cellvalue] dans un type de dictionnaire. – Vegar

0

"... et les boutons (button1 et button2) de Form1 fonctionnent uniquement avec le premier StringGrid mais pas avec le nouveau ajouté.J'ai lu quelque part que pour résoudre ce problème ..."

Il n'y a pas de méthode générique pour la résolution de cette Delphi propose différents outils pour le résoudre

  1. Vous pouvez créer une liste d'objets (TObjectList) qui containts tous les StringGrid;.. A Button1 Cliquez si vous doit rechercher ce qui est la grille que vous utilisez en ce moment, par exemple (BIS pour les autres boutons).

var 
    index:integer; 
    sg:TStringGrid; 
begin 
    ... 
    // search the active page 
    index := pageControl.ActivePageIndex; //0, 1, 2,... 
    // USe this for search the StringGrid 
    sg := TStringGrid(OList.Objects[index]); 
    // the code that you have at the event bus woking with sg 
    // not stringgrid1, stringgrid2,... 
    ... 
    sg.Color :=  
    ... 

Si vous ne voulez pas utiliser ObjectList, il existe des alternatives. Vous pouvez utiliser la propriété Tag pour tous les StringGrids. Attribuer 0, 1, 2, 3, ...
Extrait l'index (page active) et recherche dans le TStringGrid qui ont la propriété Tag avec la même valeur. Vous pouvez le faire avec FindComponent. Le premier methos est meilleur. ;-)

Cordialement. P.D: Excuse pour mon mauvais anglais.

+0

L'idée d'ObjectList et votre anglais sont bien :) –

1

Un choix difficile pour un apprenant :) mais vous n'avez pas besoin de commencer les choses en continu.

Regardez le Assign() procédure de TPersistent c'est la routine, vous devez copier des parties de la grille facilement. Par exemple

for i := 0 to StringGrid1.RowCount - 1 do 
    StringGrid2.Rows[i].Assign(StringGrid1.Rows[i]); 

pour un démarrage facile de différencier vos grilles avec la propriété Tag (StringGrid1.Tag: = 1, StringGrid2.Tag: = 2 Etc.

Le menu contextuel est assez simple aussi:

StringGrid2.popupmenu := stringGrid1.popupMenu Mais alors vous devez décider dans la routine Popup Quelle grille est « active » quelque chose comme l

Tform1.popupMenuItem1Click(Sender: TObject) 
    if Sender is TStringGrid then 
    Case TStrigngGrid(Sender).Tag of 
    1: // Grid 1 
    2: // Grid 2 

vous pouvez utiliser la même logique simple avec le butto ns.

Comme mentionné neftali la meilleure chose serait de mettre les grilles créées dans un ObjectList. Vous pouvez ensuite finir avec le peu plus complexe, mais expandabe:

Tform1.popupMenuItem1Click(Sender: TObject) 
var AGrid: TStringGrid; 

    if Sender is TStringGrid then 
    AGrid := MyListOfStringGrids[MyListOfStringGrids.IndexOf(Sender)]; 
     DoMenuItem1Stuff(AGrid); 

Amusez-vous

+0

Ce PopupMenuItemClick semble prometteur et semble aider à résoudre une partie du problème! Merci. Je vais vérifier maintenant. A propos des grilles, eh bien, je n'ai pas besoin de copier le contenu de la grille. J'ai besoin de copier certaines propriétés et méthodes de la première grille dans une nouvelle grille créée à l'exécution. Si j'utilise le TadvStringGrid, comme suggéré par Vegar, les choses vont encore plus mal ... –