Gerenciar conectores em apresentações em Java
Visão geral
Um conector é uma linha que pode permanecer anexada a duas formas quando qualquer uma das formas se move. Suas extremidades se conectam a locais de conexão, representados por pontos verdes no PowerPoint. Alguns conectores dobrados e curvos também expõem pontos de ajuste, representados por pontos laranja, que controlam a posição dos segmentos individuais do conector.
Aspose.Slides representa conectores por meio da interface IConnector . Você pode criá‑los, anexar suas extremidades a formas, escolher locais de conexão, reroute‑los e modificar a geometria dos conectores que têm pontos de ajuste.
Tipos de Conector
A classe ShapeType inclui predefinições de conectores retos, dobrados e curvos. A tabela a seguir mostra as geometrias de conectores disponíveis e o número de pontos de ajuste definidos por cada predefinição.
| Conector | Imagem | Número de pontos de ajuste |
|---|---|---|
ShapeType.Line |
![]() |
0 |
ShapeType.StraightConnector1 |
![]() |
0 |
ShapeType.BentConnector2 |
![]() |
0 |
ShapeType.BentConnector3 |
![]() |
1 |
ShapeType.BentConnector4 |
![]() |
2 |
ShapeType.BentConnector5 |
![]() |
3 |
ShapeType.CurvedConnector2 |
![]() |
0 |
ShapeType.CurvedConnector3 |
![]() |
1 |
ShapeType.CurvedConnector4 |
![]() |
2 |
ShapeType.CurvedConnector5 |
![]() |
3 |
O número e o significado dos pontos de ajuste fazem parte da predefinição de conector selecionada. Não presuma que dois tipos diferentes de conector exponham a mesma estrutura de coleção.
Conectar duas formas
Use IShapeCollection.addConnector para adicionar um conector, e use IConnector.setStartShapeConnectedTo e IConnector.setEndShapeConnectedTo para anexar suas extremidades. Após ambas as extremidades serem anexadas, IConnector.reroute seleciona uma rota curta entre as formas.
O exemplo a seguir conecta uma elipse e um retângulo com um conector dobrado:
import com.aspose.slides.*;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IAutoShape ellipse = slide.getShapes().addAutoShape(ShapeType.Ellipse, 40, 80, 120, 80);
IAutoShape rectangle = slide.getShapes().addAutoShape(ShapeType.Rectangle, 320, 240, 140, 80);
IConnector connector = slide.getShapes().addConnector(ShapeType.BentConnector2, 0, 0, 10, 10);
connector.setStartShapeConnectedTo(ellipse);
connector.setEndShapeConnectedTo(rectangle);
connector.reroute();
presentation.save("connected-shapes.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Warning
Chamarreroute pode alterar os valores de setStartShapeConnectionSiteIndex e setEndShapeConnectionSiteIndex. Atribua sites de conexão específicos após o reroute se esses sites precisarem permanecer fixos.
Escolher um local de conexão
Cada forma que pode ser conectada informa seu número de sites por meio de IShape.getConnectionSiteCount. Valide um índice de site baseado em zero preferido antes de atribuí‑lo a uma extremidade do conector; a contagem de sites varia conforme a geometria da forma.
Este exemplo anexa o conector a um site específico na elipse quando esse site existe:
import com.aspose.slides.*;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IAutoShape ellipse = slide.getShapes().addAutoShape(ShapeType.Ellipse, 40, 80, 120, 80);
IAutoShape rectangle = slide.getShapes().addAutoShape(ShapeType.Rectangle, 320, 240, 140, 80);
IConnector connector = slide.getShapes().addConnector(ShapeType.BentConnector3, 0, 0, 10, 10);
connector.setStartShapeConnectedTo(ellipse);
connector.setEndShapeConnectedTo(rectangle);
long preferredSiteIndex = 2;
if (preferredSiteIndex < ellipse.getConnectionSiteCount()) {
connector.setStartShapeConnectionSiteIndex(preferredSiteIndex);
} else {
System.out.println("The ellipse has only " + ellipse.getConnectionSiteCount() + " connection sites.");
}
presentation.save("specific-connection-site.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Ajustar um ponto de conector
Conectores com pontos de ajuste os expõem por meio de IGeometryShape.getAdjustments. Inspecione cada IAdjustValue e verifique o valor de getType antes de alterá‑lo com setRawValue. As regras gerais para identificar ajustes de forma predefinidos são descritas em Shape Manipulation.
O número, a ordem, o significado e a faixa de valores válidos dos ajustes de conector dependem da predefinição do conector. O tipo de ajuste é somente leitura, enquanto o valor do ajuste pode ser escrito. O método somente leitura getName fornece identificação adicional quando um conector contém mais de um ajuste do mesmo tipo semântico.
Roteando ao redor de um obstáculo
No layout a seguir, um conector BentConnector5 entre duas formas passa por uma terceira forma:

Este código cria o conector obstruído:
import com.aspose.slides.*;
import java.awt.Color;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
slide.getShapes().addAutoShape(ShapeType.Rectangle, 300, 150, 150, 75);
IAutoShape sourceShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 500, 400, 100, 50);
IAutoShape targetShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 70, 30);
IConnector connector = slide.getShapes().addConnector(ShapeType.BentConnector5, 20, 20, 400, 300);
connector.getLineFormat().setEndArrowheadStyle(LineArrowheadStyle.Triangle);
connector.getLineFormat().getFillFormat().setFillType(FillType.Solid);
connector.getLineFormat().getFillFormat().getSolidFillColor().setColor(Color.BLACK);
connector.setStartShapeConnectedTo(sourceShape);
connector.setEndShapeConnectedTo(targetShape);
connector.setStartShapeConnectionSiteIndex(2);
presentation.save("connector-obstruction.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Mover a curva vertical altera a rota de modo que o conector contorne o obstáculo:

Ao invés de presumir que o índice de coleção 1 sempre representa a curva vertical, este exemplo procura por ConnectorBendPositionY e a altera somente quando o tipo semântico esperado está presente:
import com.aspose.slides.*;
import java.awt.Color;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
slide.getShapes().addAutoShape(ShapeType.Rectangle, 300, 150, 150, 75);
IAutoShape sourceShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 500, 400, 100, 50);
IAutoShape targetShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 70, 30);
IConnector connector = slide.getShapes().addConnector(ShapeType.BentConnector5, 20, 20, 400, 300);
connector.getLineFormat().setEndArrowheadStyle(LineArrowheadStyle.Triangle);
connector.getLineFormat().getFillFormat().setFillType(FillType.Solid);
connector.getLineFormat().getFillFormat().getSolidFillColor().setColor(Color.BLACK);
connector.setStartShapeConnectedTo(sourceShape);
connector.setEndShapeConnectedTo(targetShape);
connector.setStartShapeConnectionSiteIndex(2);
IAdjustValue verticalBend = null;
for (int adjustmentIndex = 0; adjustmentIndex < connector.getAdjustments().size(); adjustmentIndex++) {
IAdjustValue adjustment = connector.getAdjustments().get_Item(adjustmentIndex);
System.out.println(adjustment.getName() + ": " + adjustment.getType() + ", raw value = " + adjustment.getRawValue());
if (adjustment.getType() == ShapeAdjustmentType.ConnectorBendPositionY) {
verticalBend = adjustment;
break;
}
}
if (verticalBend == null) {
System.out.println("The connector does not expose a vertical bend adjustment.");
} else {
verticalBend.setRawValue(60000);
presentation.save("connector-obstruction-fixed.pptx", SaveFormat.Pptx);
}
} finally {
presentation.dispose();
}
BentConnector5 tem dois ajustes ConnectorBendPositionX e um ajuste ConnectorBendPositionY. Se o tipo que você precisa ocorre mais de uma vez, inspecione getName e a geometria conhecida dessa predefinição antes de selecionar um. Se um ajuste reporta ShapeAdjustmentType.Custom, trate seu significado e faixa como específicos da predefinição e não o altere até que esse contrato seja conhecido.
Relacionar valores de ajuste à geometria do conector
Para conectores dobrados, os valores de ajuste podem ser usados para estimar as posições dos segmentos individuais. Esses cálculos são específicos da predefinição do conector:
BentConnector4normalmente expõe um ajusteConnectorBendPositionXe um ajusteConnectorBendPositionY.- Para essas posições de curva, dividir o valor retornado por
getRawValuepor100000fproduz a fração da largura ou altura da moldura do conector utilizada nos exemplos abaixo. - Uma moldura de conector pode ser rotacionada ou invertida, portanto as coordenadas da moldura devem ser transformadas antes de serem comparadas com as coordenadas do slide.
Os exemplos a seguir usam getType para identificar os ajustes primeiro. Eles não tratam índices de coleção como identificadores portáteis.
Conector não rotacionado
O layout inicial contém duas formas de texto conectadas por um BentConnector4:

Este exemplo inspeciona o conector e obtém seus ajustes de curva horizontal e vertical:
import com.aspose.slides.*;
import java.awt.Color;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IAutoShape sourceShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 60, 25);
sourceShape.getTextFrame().setText("From");
IAutoShape targetShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 500, 100, 60, 25);
targetShape.getTextFrame().setText("To");
IConnector connector = slide.getShapes().addConnector(ShapeType.BentConnector4, 20, 20, 400, 300);
connector.getLineFormat().setEndArrowheadStyle(LineArrowheadStyle.Triangle);
connector.getLineFormat().getFillFormat().setFillType(FillType.Solid);
connector.getLineFormat().getFillFormat().getSolidFillColor().setColor(Color.RED);
connector.getLineFormat().setWidth(3);
connector.setStartShapeConnectedTo(sourceShape);
connector.setStartShapeConnectionSiteIndex(3);
connector.setEndShapeConnectedTo(targetShape);
connector.setEndShapeConnectionSiteIndex(2);
for (int adjustmentIndex = 0; adjustmentIndex < connector.getAdjustments().size(); adjustmentIndex++) {
IAdjustValue adjustment = connector.getAdjustments().get_Item(adjustmentIndex);
System.out.println(adjustment.getName() + ": " + adjustment.getType() + ", raw value = " + adjustment.getRawValue());
}
} finally {
presentation.dispose();
}
Para alterar ambas as curvas, localize cada tipo esperado e modifique os valores somente após ambos serem encontrados:
import com.aspose.slides.*;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IAutoShape sourceShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 60, 25);
IAutoShape targetShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 500, 100, 60, 25);
IConnector connector = slide.getShapes().addConnector(ShapeType.BentConnector4, 20, 20, 400, 300);
connector.setStartShapeConnectedTo(sourceShape);
connector.setStartShapeConnectionSiteIndex(3);
connector.setEndShapeConnectedTo(targetShape);
connector.setEndShapeConnectionSiteIndex(2);
IAdjustValue horizontalBend = null;
IAdjustValue verticalBend = null;
for (int adjustmentIndex = 0; adjustmentIndex < connector.getAdjustments().size(); adjustmentIndex++) {
IAdjustValue adjustment = connector.getAdjustments().get_Item(adjustmentIndex);
if (adjustment.getType() == ShapeAdjustmentType.ConnectorBendPositionX) {
horizontalBend = adjustment;
} else if (adjustment.getType() == ShapeAdjustmentType.ConnectorBendPositionY) {
verticalBend = adjustment;
}
}
if (horizontalBend == null || verticalBend == null) {
System.out.println("The connector does not expose the expected bend adjustments.");
} else {
horizontalBend.setRawValue(horizontalBend.getRawValue() + 20000);
verticalBend.setRawValue(verticalBend.getRawValue() + 200000);
presentation.save("connector-adjusted.pptx", SaveFormat.Pptx);
}
} finally {
presentation.dispose();
}
O resultado é um conector cujos segmentos horizontal e vertical foram movidos:

Uma vez que os tipos semânticos são conhecidos, seus valores podem ser convertidos em coordenadas da moldura do conector. Este exemplo desenha um retângulo fino sobre o segmento vertical controlado pelos dois ajustes de curva:
import com.aspose.slides.*;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IAutoShape sourceShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 60, 25);
IAutoShape targetShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 500, 100, 60, 25);
IConnector connector = slide.getShapes().addConnector(ShapeType.BentConnector4, 20, 20, 400, 300);
connector.setStartShapeConnectedTo(sourceShape);
connector.setStartShapeConnectionSiteIndex(3);
connector.setEndShapeConnectedTo(targetShape);
connector.setEndShapeConnectionSiteIndex(2);
IAdjustValue horizontalBend = null;
IAdjustValue verticalBend = null;
for (int adjustmentIndex = 0; adjustmentIndex < connector.getAdjustments().size(); adjustmentIndex++) {
IAdjustValue adjustment = connector.getAdjustments().get_Item(adjustmentIndex);
if (adjustment.getType() == ShapeAdjustmentType.ConnectorBendPositionX) {
horizontalBend = adjustment;
} else if (adjustment.getType() == ShapeAdjustmentType.ConnectorBendPositionY) {
verticalBend = adjustment;
}
}
if (horizontalBend == null || verticalBend == null) {
System.out.println("The connector does not expose the expected bend adjustments.");
} else {
float x = connector.getX() + connector.getWidth() * horizontalBend.getRawValue() / 100000f;
float y = connector.getY();
float height = connector.getHeight() * verticalBend.getRawValue() / 100000f;
slide.getShapes().addAutoShape(ShapeType.Rectangle, x, y, 1, height);
presentation.save("connector-segment-guide.pptx", SaveFormat.Pptx);
}
} finally {
presentation.dispose();
}
A forma guia marca o segmento calculado:

Conector rotacionado ou invertido
Quando a mesma geometria de conector está orientada verticalmente, seus valores de IShape.getFrame, ShapeFrame.getFlipH, e ShapeFrame.getFlipV afetam a conversão das coordenadas da moldura do conector para coordenadas do slide.
Este exemplo cria e ajusta o conector orientado verticalmente:
import com.aspose.slides.*;
import java.awt.Color;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IAutoShape sourceShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 60, 25);
sourceShape.getTextFrame().setText("From");
IAutoShape targetShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 400, 60, 25);
targetShape.getTextFrame().setText("To 1");
IConnector connector = slide.getShapes().addConnector(ShapeType.BentConnector4, 20, 20, 400, 300);
connector.getLineFormat().setEndArrowheadStyle(LineArrowheadStyle.Triangle);
connector.getLineFormat().getFillFormat().setFillType(FillType.Solid);
connector.getLineFormat().getFillFormat().getSolidFillColor().setColor(new Color(102, 205, 170));
connector.getLineFormat().setWidth(3);
connector.setStartShapeConnectedTo(sourceShape);
connector.setStartShapeConnectionSiteIndex(2);
connector.setEndShapeConnectedTo(targetShape);
connector.setEndShapeConnectionSiteIndex(3);
for (int adjustmentIndex = 0; adjustmentIndex < connector.getAdjustments().size(); adjustmentIndex++) {
IAdjustValue adjustment = connector.getAdjustments().get_Item(adjustmentIndex);
if (adjustment.getType() == ShapeAdjustmentType.ConnectorBendPositionX) {
adjustment.setRawValue(adjustment.getRawValue() + 20000);
} else if (adjustment.getType() == ShapeAdjustmentType.ConnectorBendPositionY) {
adjustment.setRawValue(adjustment.getRawValue() + 200000);
}
}
presentation.save("vertical-connector-adjusted.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
O conector ajustado aparece verticalmente entre as formas:

Para um ângulo de rotação arbitrário alpha, rotacione um ponto da moldura do conector (x, y) ao redor do centro da moldura (x0, y0):
X = (x - x0) * cos(alpha) - (y - y0) * sin(alpha) + x0
Y = (x - x0) * sin(alpha) + (y - y0) * cos(alpha) + y0
O código a seguir trata a orientação de 90 graus usada neste exemplo e desenha um guia vermelho sobre o segmento correspondente do conector:
import com.aspose.slides.*;
import java.awt.Color;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IAutoShape sourceShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 60, 25);
IAutoShape targetShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 400, 60, 25);
IConnector connector = slide.getShapes().addConnector(ShapeType.BentConnector4, 20, 20, 400, 300);
connector.setStartShapeConnectedTo(sourceShape);
connector.setStartShapeConnectionSiteIndex(2);
connector.setEndShapeConnectedTo(targetShape);
connector.setEndShapeConnectionSiteIndex(3);
IAdjustValue horizontalBend = null;
IAdjustValue verticalBend = null;
for (int adjustmentIndex = 0; adjustmentIndex < connector.getAdjustments().size(); adjustmentIndex++) {
IAdjustValue adjustment = connector.getAdjustments().get_Item(adjustmentIndex);
if (adjustment.getType() == ShapeAdjustmentType.ConnectorBendPositionX) {
horizontalBend = adjustment;
} else if (adjustment.getType() == ShapeAdjustmentType.ConnectorBendPositionY) {
verticalBend = adjustment;
}
}
if (horizontalBend == null || verticalBend == null) {
System.out.println("The connector does not expose the expected bend adjustments.");
} else {
horizontalBend.setRawValue(horizontalBend.getRawValue() + 20000);
verticalBend.setRawValue(verticalBend.getRawValue() + 200000);
float x = connector.getX();
float y = connector.getY();
if (connector.getFrame().getFlipH() == NullableBool.True) {
x += connector.getWidth();
}
if (connector.getFrame().getFlipV() == NullableBool.True) {
y += connector.getHeight();
}
x += connector.getWidth() * horizontalBend.getRawValue() / 100000f;
float rotatedX = connector.getFrame().getCenterX() - y + connector.getFrame().getCenterY();
float rotatedY = x - connector.getFrame().getCenterX() + connector.getFrame().getCenterY();
float segmentWidth = connector.getHeight() * verticalBend.getRawValue() / 100000f;
IAutoShape guide = slide.getShapes().addAutoShape(ShapeType.Rectangle, rotatedX, rotatedY, segmentWidth, 1);
guide.getLineFormat().getFillFormat().setFillType(FillType.Solid);
guide.getLineFormat().getFillFormat().getSolidFillColor().setColor(Color.RED);
presentation.save("rotated-connector-segment-guide.pptx", SaveFormat.Pptx);
}
} finally {
presentation.dispose();
}
O guia vermelho marca o segmento calculado após a transformação de coordenadas:

Essas fórmulas descrevem as predefinições usadas nos exemplos, não um modelo universal de conector. Valide os tipos de ajuste, a orientação da moldura e as faixas de valores antes de aplicar o mesmo cálculo a uma predefinição diferente.
Encontrar o ângulo de direção de um conector
A direção de um conector reto pode ser calculada a partir de sua largura e altura, com inversões horizontais e verticais aplicadas. O exemplo a seguir relata o ângulo horário a partir do eixo horizontal positivo nas coordenadas do slide:
import com.aspose.slides.*;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IConnector connector = slide.getShapes().addConnector(ShapeType.StraightConnector1, 100, 100, 200, 100);
boolean flipH = connector.getFrame().getFlipH() == NullableBool.True;
boolean flipV = connector.getFrame().getFlipV() == NullableBool.True;
float deltaX = connector.getWidth() * (flipH ? -1 : 1);
float deltaY = connector.getHeight() * (flipV ? -1 : 1);
double angle = Math.atan2(deltaY, deltaX) * 180.0 / Math.PI;
if (angle < 0) {
angle += 360;
}
System.out.printf("Connector direction: %.2f degrees%n", angle);
} finally {
presentation.dispose();
}
Perguntas frequentes
Como posso saber se um conector pode ser anexado a uma forma?
Verifique o valor de getConnectionSiteCount da forma. Uma contagem positiva indica que a forma expõe sites de conexão. Valide o índice de site selecionado antes de atribuí‑lo a qualquer extremidade do conector.
Posso identificar um ajuste de conector pelo seu índice de coleção?
Um índice só tem significado para uma predefinição de conector conhecida e sua estrutura de coleção. Verifique IAdjustValue.getType antes de modificar um valor, e use IAdjustValue.getName como informação adicional quando o mesmo tipo semântico ocorre mais de uma vez.
O que acontece quando uma forma conectada é excluída?
A extremidade do conector correspondente fica desanexada. O conector permanece no slide e pode ser excluído, posicionado como uma linha livre ou anexado a outra forma.
As ligações do conector são preservadas ao copiar um slide?
As ligações geralmente são preservadas quando as formas conectadas são copiadas juntamente com o slide. Se um conector for copiado sem uma de suas formas‑alvo, a extremidade afetada deve ser anexada novamente.









